Bash

為什麼殭屍在等待它的孩子?

  • August 15, 2016

我正在探勘不同的來源,但找不到對兒童收割解剖結構的良好描述。這是我想了解的一個簡單案例。

$ 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 原始碼才能更廣泛地理解這一點,或者是否有任何文件?我已經諮詢過:

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)會收穫它。

另請參閱linux 如何處理殭屍程序殭屍可以有孤兒嗎?收割喪屍會打擾孤兒嗎?

引用自:https://unix.stackexchange.com/questions/303392