execve и цикл чтения

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

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

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

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

#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 (), когда мой дочерний процесс завершается.

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

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


person Jérémy Caudal    schedule 27.03.2020    source источник
comment
Обратите внимание, что ft_putstr(buf); может завершиться ошибкой, поскольку длинный buf определенно не содержит нулевого символа.   -  person chux - Reinstate Monica    schedule 27.03.2020


Ответы (1)


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

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

person ensc    schedule 27.03.2020
comment
Спасибо за повтор. Я не понимаю, зачем закрывать ту сторону трубы, которая не используется в процессе. Я думаю, мне нужно прочитать больше об этом. - person Jérémy Caudal; 27.03.2020