子进程之间的UNIX管道

时间:2011-02-20 21:56:17

标签: c shell process exec pipe

我正在尝试编写一个程序,它将生成任意数量的子进程并在它们之间进行管道传输,类似于命令行管道。在我的情况下,我正在尝试“ls -l | more”并将其输出到stdout,然后让父级继续执行更多命令。

我将以下代码作为最小例子:

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”来减少更多的输出和“你”上升,它似乎工作正常。但是当我到达底部,而不是像更多的那样退出时,它只留下一个空白。 Ctrl-C用于退出它,但退出整个程序,意味着“完成!”线从未打印过。有一部电影here可以说明会发生什么(请注意,最后我按Ctrl-C返回bash)。

对此有何想法?我只想弄清楚如何将其更改为位置,而不是在更多到达底部之后转到空行,更多退出并返回到父进程,以便它可以继续执行。

2 个答案:

答案 0 :(得分:9)

您至少需要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;
}

答案 1 :(得分:-1)

我认为这是因为wait() function。遵循逻辑,您的第二个子进程输出到第一个子进程,这意味着它应该首先结束,而不是第二个进程。

wait函数中,您正在等待第一个进程结束,但您不是在等待第二个进程。这意味着如果第二个进程没有向输出发送EOF,我猜你的第一个进程将不会结束。

您可以尝试等待第二个过程而不是第一个过程,并查明是否存在问题。