C语言实现Unix管道命令时sort指令无输出问题求助
sort和head的核心行为差异
head属于流式处理工具:默认只需要读取前10行输入就能输出结果,读取到足够行数后会直接终止进程,不需要等待输入流完全结束。就算上游还没发送完所有数据,只要满足输出条件它就会立刻返回,所以你能看到输出。sort属于全量处理工具:它需要拿到所有输入内容才能完成排序逻辑,只有当输入流完全关闭(收到EOF信号)时,才会输出最终的排序结果。只要输入流还有任意一个打开的写端,sort就会一直等待后续输入,不会产生任何输出。
你代码中导致sort卡住的根本原因
管道的读写规则是:只有当所有持有管道写端的进程都关闭了该写端,读端进程才能收到EOF,结束读取。你的代码犯了管道编程最常见的错误:没有关闭所有不需要的管道文件描述符,具体问题如下:
- 父进程在创建完所有管道、fork完所有子进程后,没有关闭自己持有的所有管道的读写端。比如pdesk3、pdesk4、pdesk5的写端,父进程一直持有没有关闭,导致下游
sort的输入流永远不会收到EOF,所以一直卡住等待输入。 - 你注释了第一个
sort进程中dup2(pdesk4[1], 1);这行代码,导致sort的输出没有连接到下游uniq的输入管道,而是直接输出到终端,同时pdesk4的写端没有被任何进程持有,后续uniq也收不到输入。 - 你在fork第一个
sort之前提前调用了wait(NULL)等待cut进程退出,虽然这个操作不会直接导致卡住,但不符合管道并行执行的设计逻辑,没有必要。 - 你的pipe创建失败检测逻辑完全错误:
pdesk1是数组名,作为栈上指针永远是正数,你放在if里判断pdesk1 <0永远不会触发,正确写法是把pipe调用放到判断条件里:
if (pipe(pdesk1) < 0 || pipe(pdesk2) < 0 || pipe(pdesk3) < 0 || pipe(pdesk4) < 0 || pipe(pdesk5) < 0) { perror("pipe"); exit(1); }
修复建议
- 所有子进程在完成
dup2重定向后,必须关闭当前进程不需要用到的所有管道的所有文件描述符,不要遗漏任何一个。 - 父进程在fork完全部子进程后,一次性关闭自己手里所有的管道文件描述符,保证所有管道的写端只被需要的上游子进程持有。
- 不要在fork子进程的中间调用
wait,等所有子进程都创建完成后再统一等待所有子进程退出。
内容的提问来源于stack exchange,提问作者wroot
相关产品推荐
相关产品推荐

