我不明白以下内容:
mkfifo p;
$ (>p ps -f | >>p echo $BASHPID) &
[1] 983527
$ cat p
983529
PID PPID C STIME TTY TIME CMD
981815 165343 0 19:57 pts/27 00:00:00 bash
983527 981815 0 21:09 pts/27 00:00:00 bash # <- child bash process `(...)`
983528 983527 0 21:09 pts/27 00:00:00 ps -f
983530 981815 0 21:09 pts/27 00:00:00 cat p
(...) &
结果是一个 PID 为 983527 的子进程。它是一个 bash 进程。
ps -f
在 PID 为 983528的子进程中执行。(...)
它是管道的左侧组件命令...|...
。
echo $BASHPID
报告正在 PID 为 983529 的进程中执行。它应该是管道的右侧组件...|...
,并且应该被列为 bash 进程。
最后的解释正确吗?为什么我们看不到ps -f
命令列出的最后一个进程?
答案1
>p ps -f | >>p echo $BASHPID
inbash
同时启动两个子进程,通过管道连接。两个进程都p
以只写模式打开 fifo 开始(带有O_APPEND
第二个进程的标志,但这对管道没有影响)。
由于该 fifo 还没有读取器,因此两个open()
s 都会挂在那里,等待某个进程以读取模式打开 fifo。
因此,在那时,您已经拥有了这两个流程的起点。
左边的仍然需要执行,ps
这意味着查找并加载/bin/ps
可执行文件,加载动态链接器,加载和链接库,开始读取/proc
等等,这是很多工作。虽然正确的做法是 Expand $BASHPID
,对其执行 split+glob ,调用echo
内置函数(仅调用内部函数),该函数仅写入该扩展并退出。
运行时cat p
,只要cat
打开fifo,上面的两个进程就会同时解除阻塞。正确的 ( echo
) 可能已经完成了简单的工作并在ps
完成加载之前很久就退出了,因此ps
不会找到它,/proc
这解释了为什么您看不到它。
1 并且它的死亡将得到其父进程的确认,否则该进程仍将显示为僵尸进程