在这种特殊情况下如何处理管道

How to handle pipes in this special case

我创建了一个简单的管道,ls -l /usr/bin 命令的结果使用分支 (child) 进程写入其中。然后在主 (parent) 过程中,我只是等待 child 完成。

    int fd[2];
    char* arg[] = {"ls", "-l" , "/usr/bin/", NULL};

    pipe(fd);

    if (fork()==0) //child
    {
        dup2(fd[1], 1);
        close(fd[0]);
        close(fd[1]);

        execvp(arg[0],arg);
    }
    else //parent
    {
        // close(fd[0]);
        close(fd[1]);       
        wait(NULL);
    }

在执行dup2后的child进程中,我关闭了管道的两端,因为我不再需要它们了。在 parent 中,我只关闭写入端,因为 我需要读取端

如果执行此代码,它将停止。 BUT,如果命令是 ls -l ~/Desktop/ 或类似的命令,它将成功终止。

显然 ls -l /usr/bin 命令比 ls -l ~/Desktop/ 花费更多时间,但我认为这仍然没有关系,它们都必须终止。

在 parent 中,如果我也关闭管道的读取端,程序将终止(我不希望这样)。

这种行为的原因是什么?有什么解决方法可以克服它吗?

问题是管道的容量是有限的(POSIX 允许非常小,比如 4 KiB;Linux 最多可以允许大约 64 KiB,并且 Mac OS X 最多允许 64 KiB)。写进程写完这么多数据后,没有读进程读,就一直阻塞,直到读进程读到一些数据,或者最后一个读进程挂掉,没有进程可以读数据。

管道用于并发执行程序。您通过尝试使第一个程序在下一个程序开始之前完成来强制顺序执行。这是不正确的。您需要确保在等待它们完成之前启动管道中的所有进程