为什么 wait() 函数(系统调用)从不 return (无限等待)

Why wait() funtion ( system call ) never return ( make an infinity wait)

我想模拟管道命令:ls |排序 | wc -l 通过编写一些代码但我遇到了一个奇怪的问题(我可以通过删除该行来解决它但我不知道它是错误的原因) 当我删除最后一个等待命令时,它 运行 完全正确并完成。但是当我添加这个时,它会无限等待。

int main()
{
        
    int pfds[2];

    int pfds1[2];

    pipe(pfds);     // create a pipe

    pid_t pid = fork();   // create child proess
      
    if (pid == 0)           // child process
    {
        dup2(pfds[1],1);     // change the stdout to pipe
        close(pfds[0]);
        execlp("ls", "ls", NULL);    // run the ls command
    }
    else {                   //  main process
        wait(0);           // wait for the child process
        pipe(pfds1);          //  make a pipe
        pid_t npid = fork();     // create child process

        if (npid == 0)              // child process
        {
            dup2(pfds[0],0);             // change the stdin to pipe
            close(pfds[1]); 
            dup2(pfds1[1], 1);              // get data from pipe
            close(pfds1[0]);
            execlp("sort", "sort", NULL);     // run sort command ( combine with above is ls | sort )
        }
        else {       // main process
            wait(0);             // this line will make infinity wait 
            dup2(pfds[0], 0);                      
            close(pfds[1]); 
            execlp("wc", "wc", "-l", NULL);              // run wc -l command 
        }
    }
    return 0;
}

你没有关闭你应该关闭的 fds。请记住,只有在所有文件描述符都关闭后,文件句柄才会关闭。例如,如果您不小心,可能 ls 已经完成但 sort 没有意识到这一点,因为缺少 close.

此外,您的代码容易出现死锁。如果 ls 要输出大量数据,它将写入第一个管道,直到它满了并阻塞。 parent 没有清空管道,而是等待 child 结束。死锁。

确保关闭不再需要的 fds,并在等待任何结束之前每隔 children 启动一次。

int pfds1[2]; pipe(pfds1);

pid_t pid1 = fork();
if (!pid1) {
   close(pfds1[0]);
   dup2(pfds1[1], 1); close(pfds1[1]);
   execlp("ls", "ls", NULL);
}

close(pfds1[1]);

int pfds2[2]; pipe(pfds2);

pid_t pid2 = fork();
if (!pid2) {
   close(pfds2[0]);
   dup2(pfds1[0], 0); close(pfds1[0]);
   dup2(pfds2[1], 1); close(pfds2[1]);
   execlp("sort", "sort", NULL);
}

close(pfds2[1]);

pid_t pid3 = fork();
if (!pid3) {
   dup2(pfds2[0], 0); close(pfds2[0]);
   execlp("wc", "wc", "-l", NULL);
}

waitpid(pid1, NULL, 0);
waitpid(pid2, NULL, 0);
waitpid(pid3, NULL, 0);