為什麼殭屍在等待它的孩子?
我正在探勘不同的來源,但找不到對兒童收割解剖結構的良好描述。這是我想了解的一個簡單案例。
$ cat <( sleep 100 & wait ) & [1] 14247 $ ps ax -O pgid | grep $$ 12126 12126 S pts/17 00:00:00 bash 14248 12126 S pts/17 00:00:00 bash 14249 12126 S pts/17 00:00:00 sleep 100 14251 14250 S pts/17 00:00:00 grep --color=auto 12126 $ kill -2 14248 $ ps ax -O pgid | grep $$ 12126 12126 S pts/17 00:00:00 bash 14248 12126 Z pts/17 00:00:00 [bash] <defunct> 14249 12126 S pts/17 00:00:00 sleep 100 14255 14254 S pts/17 00:00:00 grep --color=auto 12126
為什麼殭屍在等孩子?
你能解釋一下這個嗎?我是否需要了解 C 並閱讀 Bash 原始碼才能更廣泛地理解這一點,或者是否有任何文件?我已經諮詢過:
- 本網站和 Stack Overflow 上的各種連結
- W. Shotts的 Linux 命令行
man bash
- Bash 參考手冊(在 Bash 原始碼文件中)
- Bash 初學者指南@ tldp.org
- 高級 Bash 腳本指南
GNU bash,版本 4.3.42(1)-release (x86_64-pc-linux-gnu)
Linux 4.4.0-31-generic #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
殭屍不是在等待它的孩子。像任何殭屍程序一樣,它會一直存在,直到其父程序收集它。
您應該顯示所有涉及的程序以了解發生了什麼,並查看 PPID。使用這個命令行:
ps -t $(tty) -O ppid,pgid
您要殺死的程序的父級是
cat
. 發生的情況是 bashcat <( sleep 100 & wait )
在子 shell 中執行後台命令。由於這個子shell 所做的唯一一件事就是設置一些重定向,然後執行一個外部命令,這個子shell 被外部命令替換。這是綱要:
- 原始 bash (12126) 呼叫以在子 (14247) 中
fork
執行後台命令。cat <( sleep 100 & wait )
子程序 (14247) 呼叫
pipe
創建管道,然後fork
創建子程序來執行程序替換sleep 100 & wait
。
- 孫子 (14248) 呼叫在後台
fork
執行sleep 100
。由於孫子程序不是互動式的,因此後台程序不會在單獨的程序組中執行。然后孫子等待sleep
退出。子 (14247) 呼叫
setpgid
(它是互動式 shell 中的後台作業,因此它擁有自己的程序組),然後execve
執行cat
. (我有點驚訝於後台程序組中沒有發生程序替換。)
- 你殺了孫子(14248)。它的父程序正在執行
cat
,它對任何子程序一無所知,也沒有業務呼叫wait
。由於孫子的父母沒有收穫,孫子作為殭屍留在後面。- 最終,
cat
退出——要麼是因為你殺死了它,要麼是因為sleep
返回並關閉了管道,所以cat
看到了它的輸入結束。那時,殭屍的父母死了,所以殭屍被 init 收集並收割它。如果將命令更改為
{ cat <( sleep 100 & wait ); echo done; } &
然後
cat
在一個單獨的程序中執行,而不是在原始 bash 程序的子程序中執行:第一個子程序必須留在後面才能執行echo done
. 在這種情況下,如果您殺死了孫子,它不會像殭屍一樣繼續存在,因為子(此時仍在執行 bash)會收穫它。