UNIX-каналы между дочерними процессами - PullRequest
7 голосов
/ 21 февраля 2011

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

У меня есть следующий код в качестве минимального примера:

int main (int argc, const char * argv[]) {
    int fd[2];
    pipe(fd); 
    chdir("/directory/with/lots/of/files");

    // Create one child process for more
    int pid = fork();
    if (pid == 0) {
        close(fd[1]);
        int ret = dup2(fd[0],0);
        if (ret < 0) perror("dup2");
        char *argv[10];
        argv[0] = "more";  argv[1] = NULL;
        execvp("more", argv);
    } 
    // Create another child process for ls
    int pid2 = fork();
    if (pid2 == 0) {
        int ret = dup2(fd[1],1);
        if (ret < 0) perror("dup2");
        char *argv[10];
        argv[0] = "ls";    argv[1] = "-l";   
        argv[2] = NULL;
        execvp("ls", argv);
    }

    // wait for the more process to finish
    int status;
    waitpid(pid, &status, 0);

    printf("Done!\n");
    return 0;
}

Теперь, когда я выполняю программу (конечно, заключенную в функцию main ()), я получаю больше, что ожидается. Я нажму «d», чтобы пролистать вывод большего, и «u», чтобы подняться, и, похоже, он работает нормально. Но когда я достигаю дна, вместо того, чтобы выходить, как другие, он просто оставляет пустую строку. Ctrl-C работает, чтобы выйти из него, но он выходит из всей программы, что означает «Готово!» линия никогда не печатается. Фильм доступен здесь , который иллюстрирует, что происходит (обратите внимание, что в самом конце я нажимаю Ctrl-C, чтобы вернуться к bash).

Есть мысли по этому поводу? Я просто пытаюсь выяснить, как изменить его, где вместо перехода к пустой строке после того, как больше достигнет дна, больше выйдет и вернется к родительскому процессу, чтобы он мог продолжить выполнение.

Ответы [ 2 ]

9 голосов
/ 21 февраля 2011

Вам нужно close() хотя бы конец записи канала, иначе more никогда не увидит EOF. Например:

    ...

    // close parent's pipes
    close(fd[0]);
    close(fd[1]);

    // wait for the more process to finish
    int status;
    waitpid(pid, &status, 0);

    printf("Done!\n");
    return 0;
}
0 голосов
/ 21 февраля 2011

Я думаю, это из-за wait() function. Следуя логике, ваш второй дочерний процесс выводится на первый дочерний процесс, то есть он должен заканчиваться первым, чем второй.

В вашей функции wait вы ожидаете завершения первого процесса, но не ожидаете второго процесса. Это означает, что если второй процесс не отправляет EOF на выход, ваш первый процесс не будет завершен, я думаю.

Вы можете попытаться дождаться второго процесса вместо первого и выяснить, в этом ли проблема.

...