Почему waitpid блокируется в этом конкретном случае? - PullRequest
1 голос
/ 06 апреля 2019

Я хочу понять, как работает pipe, но я не понимаю, почему waitpid блокируется, если вы запускаете мою программу с помощью "ls -l / usr / bin", "grep ls" .... Если вы вынулиВариант -l это работает!my_str_tab просто помещает каждое слово строки в массив charstar.

void command_levels(int *pipe_fd, char **av, int idx, int pipe_save, int pipe_one)
{
    if (idx == 1)
        dup2(pipe_fd[1], 1);
    else if (idx > 1 && av[idx + 1] != NULL) {
        dup2(pipe_save, 0);
        dup2(pipe_fd[1], 1);
    }
    if (idx > 1 && av[idx + 1] == NULL) {
        dup2(pipe_save, 0);
        dup2(pipe_one, 1);
    }
}

void multiple_pipe_handle(char **av, char **env, int idx, int pipe_one)
{
    int pipe_fd[2] = {0, 0};
    char **command = NULL;
    static int pipe_save = 0;

    if (av[idx] == NULL)
        return;
    command = my_str_tab(av[idx], " ");
    pipe(pipe_fd);
    command_levels(pipe_fd, av, idx, pipe_save, pipe_one);
    if (fork() == 0) {
        close(pipe_fd[0]);
        close(pipe_fd[1]);
        execve(command[0], command, env);
    } else {
        wait(NULL);
        close(pipe_fd[1]);
        pipe_save = pipe_fd[0];
        multiple_pipe_handle(av, env, idx + 1, pipe_one);
        close(pipe_fd[0]);
    }
}

int main(int ac, char **av, char **env)
{
    int pipe_one = dup(1);

    multiple_pipe_handle(av, env, 1, pipe_one);
}

Я ожидаю, что вывод всего слова содержит 'ls', но я нахожусь в бесконечном цикле ..

1 Ответ

2 голосов
/ 06 апреля 2019

Это распространенная ошибка при реализации конвейеров.

Когда вы передаете -l в ls, он выдает больше выходных данных, чем когда вы не пропустите эту опцию.Это позволяет ему полностью заполнить внутренний буфер канала.Ядро «блокирует» его выполнение до тех пор, пока что-то не прочитает с другого конца канала.Но с другого конца канала ничего не читается, потому что ваша родительская программа ожидает, пока ls завершит выполнение, прежде чем запустит процесс grep.Но ls не завершит выполнение, пока не сможет записать больше данных в канал, поэтому вся программа заблокирована.

Чтобы исправить эту ошибку, вы должны запустить все процессов вконвейер, прежде чем ждать любой из них.Вы не можете сделать это с помощью одного рекурсивного вызова multiple_pipe_handle.Вам нужны два цикла: один вызов fork, другой вызов waitpid и массив идентификаторов подпроцесса.Если вы намереваетесь читать результаты конечного конвейерного процесса в родительском процессе, вы должны прочитать все полученные данные (пока read не отправит сигнал EOF, возвращая ноль байтов данных) до вы не начнете вызывать waitpid.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...