C语言两个子进程间管道通信程序无限阻塞问题排查
程序阻塞原因:父进程未关闭管道描述符
你的程序之所以既不输出内容也无法正常终止,核心问题在于父进程没有关闭管道的两端描述符,导致wc命令一直阻塞等待输入,最终整个程序陷入死等状态。
问题原理剖析
管道的工作机制是:只有当管道的所有写端都被关闭时,读端的read操作才会返回EOF(即0),让读取进程知道没有更多数据了。
看你的代码流程:
- 子进程1(执行
ls):关闭了管道读端pipefd[0],将写端pipefd[1]重定向到stdout后关闭了它。当ls执行完毕退出时,stdout会被自动关闭,此时子进程1持有的写端已经关闭。 - 子进程2(执行
wc):关闭了管道写端pipefd[1],将读端pipefd[0]重定向到stdin后关闭了它。它会一直从管道读取数据,直到收到EOF才会结束统计并退出。 - 但父进程从始至终都没有关闭
pipefd[0]和pipefd[1]!这就导致管道的写端仍然被父进程持有,wc会认为可能还有数据会从写端过来,因此一直阻塞在读取操作上,永远不会退出。父进程的wait(NULL)也会一直等待子进程2结束,最终整个程序卡住。
修复方案
在父进程等待子进程的代码块中,添加关闭管道两端描述符的操作:
} else { // parent executing, waiting for two children close(pipefd[0]); // 关闭父进程持有的管道读端 close(pipefd[1]); // 关闭父进程持有的管道写端 wait(NULL); wait(NULL); }
修复后流程
父进程关闭管道两端后,管道的所有写端就只剩下子进程1的那个。当ls执行完毕退出,它的写端也会被关闭,此时管道的写端全部关闭,wc读取到EOF,就会完成统计并输出结果,随后退出。父进程的两个wait(NULL)会依次等待两个子进程结束,最终程序正常终止。
验证效果
修改后编译运行程序,你会看到类似这样的输出(具体数值取决于当前目录的文件数量):
10 10 90
内容的提问来源于stack exchange,提问作者Labeeb
相关产品推荐
相关产品推荐

