C叉的标准输出

时间:2018-12-05 12:04:59

标签: c linux shell pipe fork

我正在尝试编写一个使用管道和叉子执行ls | wc的C程序,但是我无法弄清楚我的代码出了什么问题。当我运行下面的代码时,什么也不会返回。

int main() {
    pid_t p1, p2;
    int fd1[2];

    pipe(fd1);

    p1 = fork();
    if (p1 == 0) {
        close(STDOUT_FILENO);
        dup2(fd1[1], STDOUT_FILENO);
        close(fd1[0]);
        execlp("ls", "ls", (char *)NULL);
    } else {
        p2 = fork();

        if (p2 == 0) {
            dup2(fd1[0], STDIN_FILENO);
            close(fd1[0]);
            close(fd1[1]);

            execlp("wc", "wc", (char *)NULL);
        } else {
            waitpid(p2, 0, WUNTRACED);
            waitpid(p1, 0, WUNTRACED);
        }
    }

    return 0;
}

1 个答案:

答案 0 :(得分:1)

您没有明确解释该程序在做什么,您认为这是错误的。但是,当我自己运行此程序时(在添加了适当的标题后,以后,请不要将它们放在您的问题之外),它会挂起,直到按Control-C为止。我将假设这是您不想要的,而您想要想要的是让它打印wc的输出然后退出。

程序挂起,因为在调用fd1[1]时,wait在父进程中仍处于打开状态。 wc将不会收到EOF指示,直到所有引用管道写端的文件描述符的 all 全部关闭。但是父进程在两个子进程都退出之前不会关闭管道的写侧,并且wc在获得EOF之前不会退出,因此您将陷入僵局。

您需要在close(fd1[1])的紧前面的第一个if的父侧添加p2 = fork()。这足以消除僵局。您还应该在close(fd1[0])调用之前,在 second if的父级添加waitpid。而且您还应该检查所有操作是否有错误。