我正在做我的家庭作业,那就是在C.中复制unix命令shell
我已经实现了直到后台运行(&)的单个命令执行。
现在我正处于实现管道的阶段,我面临着这个问题,对于大于1的管道,带有管道的子命令已经完成,但最终输出不会显示在stdout上(最后一个命令的stdin被最后一个管道的读取所取代)
dup2(pipes[lst_cmd], 0);
我也在家长那里试过fflush(STDIN_FILENO)
。
我的程序的出口是CONTROL-D,当我按下它时,输出就会显示出来(也会退出,因为我对CONTROL-D的操作是退出(0))。
我认为管道的输出在stdout缓冲区中,但没有显示出来。除了fflush之外,还有其他方法可以将缓冲区中的内容发送到stdout吗?
看过代码(不公平的优势)后,主要问题是流程结构与没有彻底关闭管道相结合。
管道ps | sort
的过程结构为:
main shell
- coordinator sub-shell
- ps
- sort
主shell正在创建N个管道(对于ps | sort
,N=1)。然后创建了协调器外壳;它将启动N+1个孩子。然而,它没有等待管道终止,也没有关闭管道副本。主外壳也没有关闭其管道副本。
更正常的流程结构可能没有协调器子外壳。培养孩子有两种机制。传统上,主shell会分叉一个子进程;它将对管道中的前N个进程进行协调(包括首先创建管道),然后执行管道中的最后一个进程。主shell等待一个子进程完成,管道的退出状态是子进程的退出状态(也就是管道中的最后一个进程)。
最近,bash
提供了一种机制,通过该机制,主shell可以获得管道中每个子级的状态;它进行协调。
主要的修复程序(除了一些小的编译警告)是:
- 主shell在分叉协调器之后关闭所有管道
- 主shell等待协调器完成
- 协调器在分叉管道后关闭所有管道
- 协调器等待管道中的所有进程完成
- 协调器退出(而不是返回以提供决斗的双重提示)
一个更好的修复方案将消除协调器子外壳(它的行为与所描述的经典系统类似)。