さまざまなソースを調査していますが、子供の収穫の解剖学的構造の良い説明が見つかりません。これは私が理解したい簡単なケースです。
$ 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の様々なリンク
- Linuxのコマンドライン著者: W. Shortz
man bash
- Bashリファレンスマニュアル(Bashソースコードドキュメントにあります)
- Bash初心者ガイド@tldp.org
- 高度なバッシュスクリプトガイド
GNU bash、バージョン 4.3.42(1)-リリース(x86_64-pc-linux-gnu)
Linux 4.4.0-31-一般 #50-Ubuntu SMP Wed Jul 13 00:07:12 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
答え1
ゾンビにはそれを待つ子供はいません。他のゾンビプロセスと同様に、親プロセスがそれを収集するまで存在します。
何が起こっているのかを理解し、PPIDを確認するには、関連するすべてのプロセスを表示する必要があります。次のコマンドラインを使用してください。
ps -t $(tty) -O ppid,pgid
終了するプロセスの親プロセスはですcat
。 bash はcat <( sleep 100 & wait )
サブシェルでバックグラウンドコマンドを実行します。サブシェルが実行する唯一の作業は、一部のリダイレクトを設定してから外部コマンドを実行することであるため、サブシェルは外部コマンドに置き換えられます。要約は次のとおりです。
- 元のbash(12126)呼び出しは、子プロセス(14247)でバックグラウンドコマンドを実行します
fork
。cat <( sleep 100 & wait )
- Subprocess(14247)は、
pipe
パイプを作成した後にfork
プロセス交換を実行するための子プロセスを作成するために呼び出されますsleep 100 & wait
。- Sun Tzu(14248)はバックグラウンド
fork
実行を呼び出します。sleep 100
孫プロセスは対話型ではないため、バックグラウンドプロセスは別のプロセスグループで実行されません。それから孫がsleep
出るのを待っています。
- Sun Tzu(14248)はバックグラウンド
- subprocess(14247)が呼び出された
setpgid
後(インタラクティブシェルのバックグラウンドジョブなので、独自のプロセスグループがある)execve
実行されますcat
(バックグラウンドプロセスグループでプロセスの交換が行われないことに少し驚きました)。
- Subprocess(14247)は、
- あなたは孫を殺しました(14248)。親プロセスが実行中で、
cat
子プロセスについて何も知らず、ビジネスコールもありませんwait
。孫の親が収穫をしないため、孫はゾンビのように残される。 - 結局のところ、それは終了します - あなたはそれを殺したかパイプを返して閉じて入力の終わりを見た
cat
からです。この時点で、ゾンビの親プロセスは終了するので、ゾンビはそれを取得するinitによって収集されます。sleep
cat
コマンドを次に変更すると
{ cat <( sleep 100 & wait ); echo done; } &
その後、元のcat
bashプロセスの子プロセスではなく、別のプロセスで実行されます。最初のサブプロセスは引き続き実行している必要がありますecho done
。この場合、孫を殺すと(この時点でまだbashを実行している)子は孫を収穫するため、ゾンビで続行されません。
また、見ることができますLinuxでゾンビプロセスを処理する方法そしてゾンビに孤児がありますか?孤児はゾンビを収穫することについて怒っていますか?
答え2
ゾンビは子供たちを待っていません。代わりにゾンビこれ(例のようにそれ自体または終了した)プロセスはそのコード、データ、およびスタックを解放し、現在は終了コードのみを含み、そのプロセスを検索するwait(2)
ために親呼び出しを待っています。最後に、プロセステーブルからプロセスエントリを完全にクリーンアップします。)
あなたの例では、睡眠が完了または終了すると、親は終了ステータスを読み、ゾンビを収穫します。wait(2)
詳しくは上記をご覧ください。