web-dev-qa-db-ja.com

ゾンビが子供を待っているのはなぜですか?

私はさまざまな情報源を掘り下げていますが、子刈りの解剖学についての適切な説明が見つかりません。これは私が理解したい単純なケースです。

$ 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

11
user147505

ゾンビは子供を待っていません。他のゾンビプロセスと同様に、親がそれを収集するまで、このプロセスは維持されます。

何が起こっているのかを理解するために、関連するすべてのプロセスを表示し、PPIDも確認する必要があります。次のコマンドラインを使用します。

_ps -t $(tty) -O ppid,pgid
_

強制終了しているプロセスの親はcatです。何が起こるかというと、bashはサブシェルでバックグラウンドコマンドcat <( sleep 100 & wait )を実行します。このサブシェルは、リダイレクトを設定して外部コマンドを実行するだけなので、このサブシェルは外部コマンドに置き換えられます。以下がその概要です。

  • 元のbash(12126)はforkを呼び出して、子(14247)でバックグラウンドコマンドcat <( sleep 100 & wait )を実行します。
    • 子(14247)はpipeを呼び出してパイプを作成し、次にforkを呼び出して子を作成してプロセス置換を実行します_sleep 100 & wait_。
      • 孫(14248)はforkを呼び出して、バックグラウンドで_sleep 100_を実行します。孫は対話型ではないため、バックグラウンドプロセスは別のプロセスグループで実行されません。次に孫はsleepが終了するのを待ちます。
    • 子(14247)はsetpgid(これはインタラクティブシェルのバックグラウンドジョブなので、独自のプロセスグループを取得します)を呼び出し、次にexecveを実行してcatを実行します。 (バックグラウンドプロセスグループでプロセスの置換が行われていないことに少し驚いています。)
  • あなたは孫(14248)を殺します。その親はcatを実行しています。これは子プロセスについて何も知らず、waitを呼び出すビジネスはありません。孫の親はそれを刈り取らないので、孫はゾンビとして後に残ります。
  • 最終的に、catは終了します—終了した場合、またはsleepがパイプを返して閉じ、catが入力の終わりを確認したためです。その時点で、ゾンビの親は死ぬので、ゾンビはinitによって収集され、initはそれを取得します。

コマンドを次のように変更した場合

_{ cat <( sleep 100 & wait ); echo done; } &
_

次に、catは、元のbashプロセスの子ではなく、別のプロセスで実行されます。_echo done_を実行するには、最初の子が遅れる必要があります。この場合、孫を殺しても、その子(その時点ではまだbashを実行している)がそれを取得するため、ゾンビとしてとどまることはありません。

Linuxはゾンビプロセスをどのように処理するか および ゾンビに孤児がいる可能性はありますか?孤児はゾンビを刈り取ることによって邪魔されますか? も参照してください。

ゾンビは子供を待っていません。代わりに、ゾンビはtheプロセスであり、(自分自身で、またはあなたの例のように強制終了されました)、コード、データ、スタックの割り当てが解除され、終了コードのみを含み、待機していますその親はwait(2)を呼び出してそれを取得します(したがって、最後にプロセステーブルからプロセスエントリを完全にクリーンアップします)

あなたの例では、スリープが終了する(または終了する)と、親は終了ステータスを読み取り、ゾンビを刈り取ります。詳細については、上記のwait(2)を参照してください。

6
Matija Nalis