我不明白以下内容:
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
命令列出的最后一个进程?
>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
¹ 并且它的死亡将得到其父级的承认,否则该进程仍将显示为僵尸