为什么我在等待后无法关闭管道?

问题描述

我正在尝试了解 wait() 的工作原理。这是一个在命令行中模仿 ls -F -1 | nl 的 c 程序

    pipe(fd); // create the pipe

    pid1 = fork(); //fork child 1

    if (pid1 == 0) // child 1
    {
        close(fd[0]);                       // close read end of the pipe
        dup2(fd[1],1);                     // child 1 redirects stdout to write to the pipe
        execlp("ls","bin/ls","-F",NULL); // execute ls -F
        close(fd[1]);                       // close write end of the pipe
    }

    pid2 = fork(); //fork child 2

    if (pid2 == 0) // child 2
    {
        close(fd[1]);                  // close write end of the pipe
        dup2(fd[0],0);                // child 2 redirects stdin to read from the pipe
        execlp("nl","usr/bin",NULL); // execute nl
        close(fd[0]);                  // close read end of the pipe
    }

    if (pid1 != 0 && pid2 != 0) // parent process
    {
        wait(NULL);   // wait for a child
        wait(NULL);   // wait for another child
        close(fd[0]); // close read end of parent pipe
        close(fd[1]); // close write end of parent pipe
    }

我最初认为 wait(NULL)close(fd) 的顺序无关紧要。但显然确实如此。为什么此代码在移动 wait(NULL) 下方的两个 close(fd[1]) 时继续运行而不打印任何内容正常工作?

解决方法

nlstdin 获得 EOF 之前不会退出。这不会发生,直到父母和孩子 1 都关闭了管道的写端。子 1 在退出时会这样做,父在 close(fd[1]) 时会这样做。

所以你陷入了僵局。在第二个 wait() 返回之前您不会关闭 FD,但在您关闭 FD 之前它不会返回。