выполнить и прочитать цикл - PullRequest
1 голос
/ 27 марта 2020

Я работаю над воспроизведением оболочки, которая является школьным проектом. И, как хорошие снаряды, мне нужно воспроизвести трубу | Feature.
Я кодирую прототип реализации двоичного выполнения, как /usr/bin/python.
Я работал над fork (), dup2 (), pipe () и execve (), но я мне трудно читать стандартный вывод по каналу python.

Вот что я хочу для моей демонстрационной программы: ./a.out [Путь к корзине] [argv] [...]

Вот мой ментальный аль go:
1. Я создаю трубу
2. Я форка
3. В моем ребенке я готовлю новый argv для execv
4. Я dup2 stdout в моем канале на стороне записи
5. Я выполняю execv с путем, аргументом и envp
6. В моем родителе я читаю весь контент со стороны чтения и печатаю его для проверки, в l oop, в то время как мой ребенок жив.

Вот мой код, чтобы попытаться сделать это:

#include <stdio.h>
#include <unistd.h>
#include <libgen.h>
#include <string.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <errno.h>

void    ft_putstr(char *str) { write(1, str, strlen(str)); }

char        **l_strs_nuller(char **tab, unsigned int size)
{
    char            **new;
    unsigned int    i;

    i = 0;
    if (!tab)
        return (NULL);
    if (!(new = (char**)malloc(sizeof(char*) * (size + 1))))
        return (NULL);
    while (i < size)
    {
        new[i] = strdup(tab[i]);
        i++;
    }
    new[i] = NULL;
    return (new);
}

int     main(int argc, char **argv, char **envp)
{
    char    **arg;
    pid_t   child;
    int     child_stat;
    int     pipe1[2];
    char    buf[500];

    pipe(pipe1);
    if ((child = fork()) == 0)
    {
        dup2(pipe1[1], 1); // Redirect all stdout in pipe1 write-side
        arg = l_strs_nuller(argv + 1, argc - 1); //argv + 1 to avoid a.out
        free(arg[0]); // Removing first "/usr/bin" things to put basename in the first block.
        arg[0] = strdup(basename(argv[1])); // Place file name part in the first case;
        execve(argv[1], arg, envp);
        exit(0);
    }
    else
    {
        while (waitpid(child, &child_stat, WNOHANG) == 0)
        {
            bzero(buf, 500);
            read(pipe1[0], buf, sizeof(buf));
            ft_putstr(buf);
        }
    }
    return (0);
}

Вот моя проблема: мой родительский процесс застрял в read (), когда мой ребенок завершается.

Я хотел знать, в правильном ли я направлении, и несколько советов, чтобы узнать, чего мне не хватает.

Спасибо, что читаете меня, Лобира,

1 Ответ

0 голосов
/ 27 марта 2020

Вы должны закрыть pipe1[1] в родительском процессе. В противном случае канал остается открытым, и read() не видит EOF.

Обычно вам также следует закрывать pipe1[0] в дочернем процессе, чтобы избежать подобных эффектов.

...