Порядок выполнения дочернего процесса кажется неправильным, но работает - PullRequest
3 голосов
/ 10 июля 2019

Почему следующий код выполняет команду:

"cat / etc / passwd | wc -l"

, а не

"wc -l | cat / etc / passwd"?

Несмотря на то, что операторы отладки расположены в следующем порядке

b

a

 int main() {
    pid_t pid;
    int fd[2];

    int stdOut = dup(1);

    pid = fork();
    if (pid == 0) {
        pipe(fd);
        pid = fork();
        if (pid == 0) {
            close(fd[0]);
            dup2(fd[1], STDOUT_FILENO);
            close(fd[1]);

            write(stdOut, "a\n", 2);

            execlp("cat", "cat", "/etc/passwd", NULL);
        }
        close(fd[1]);
        dup2(fd[0], STDIN_FILENO);
        close(fd[0]);

        write(stdOut, "b\n", 2);

        execlp("wc", "wc", "-l", NULL);
    }
    wait(NULL);
    return 0;
}

Ответы [ 2 ]

1 голос
/ 10 июля 2019

Порядок, в котором отображаются маркеры a и b, не коррелирует с тем, что происходит через трубу.
В настоящий момент они не синхронизируются между двумя процессами.
Команда cat записывает в свой стандартный вывод, который перенаправляется на сторону write канала.
Команда wc читает со своего стандартного ввода, который перенаправляется со стороны read канала.
Таким образом, в любом случае данные будут проходить от cat до wc через канал.

1 голос
/ 10 июля 2019

Использование pipe, dup2 и close определяет, как два процесса связаны, а не порядок выполнения. Процесс, который запускается первым, может заблокировать доступ read или write к каналу, пока другой не отправит или не получит данные соответственно.

Порядок выполнения не может быть неправильным, поскольку он не указан. Любой из родителей или детей может ждать чего-то, и планировщик не гарантирует справедливое распределение ресурсов. Может быть, создание дочернего процесса занимает некоторое время, поэтому родитель может достичь

write(stdOut, "b\n", 2);

до того, как ребенок достигнет

write(stdOut, "a\n", 2);
...