『Working with Unix Processes』の Zombie Processes を読みました
はじめに
Processes Can Wait の続きです。
まとめ
子プロセスが終了した後に親プロセスで wait するとその子プロセスの情報を得ることができる。なぜそれが可能になるのかというと、カーネルが終了した子プロセスの情報をキューイングして保持してくれるからだ。なお親プロセスが子プロセスの情報を得るタイミングで、その情報はキューから clean up される。
だが子プロセスが終了した後に親プロセスが wait していない場合、その子プロセスはゾンビプロセスとなる。子プロセスが終了した後に親プロセスが "少しでも" wait せず動き続けるのなら、その子プロセスはゾンビプロセスになりうる(※1 後述するコードを参照)。子プロセスがゾンビプロセスになっている場合、キューイングされた子プロセスの情報は残り続けメモリを無駄につかってしまう。情報を参照しないからいつまでたってもキューから clean up されないからだ。
無駄にメモリを使わないようにコードを書くことが大事だ。例えば子プロセスが終了したかどうかの情報が必要でない場合は detach しよう。そうすることで子プロセスが終了したらカーネルのキューからちゃんと clean up される。
wait と detach の使い分け
性質の違いからこんな感じに使い分けるのかなあと予想。間違ってたら教えてください><
- wait は親プロセスの処理をブロックしてもかまわないとき。detach はブロックしたくないとき
- wait は終了した子プロセスの情報を取得したいとき。detach は取得する必要のないとき
試してみた
※1 は以下のコードで確認できる。sleep している間は子プロセスは一時的にゾンビになり、wait されるとプロセスは回収される。
pid = fork { sleep 1 } puts pid sleep 20 # ※2 Process.wait
※2 で親プロセスが sleep しているときに別のターミナルから以下のコマンドを実行する。子プロセスの pid が 100 とする。
$ ps 100 PID TT STAT TIME COMMAND 100 s007 Z+ 0:00.00 (ruby)
STAT が Z+ となっており、子プロセスがゾンビになっていることが確認できる。つまり sleep 後に wait していたとしても、子プロセスが終了した後に親プロセスが少しの期間でも wait せず動き続けるのなら、その子プロセスはゾンビプロセスになりうるということがわかる。
なお、sleep のあとで wait されるので、最終的に子プロセスはゾンビではなくなり、キューから情報がちゃんと clean up される。
蛇足だが、Z+ の Z はゾンビを示し、+ はフォアグラウンドで動いていることを示す。```$ man ps``` すると色々な STAT の種類を見ることができる。
わからなかった単語やフレーズ
- lest: 【接続詞】〜しないように。rest と混同しないように注意
- rectify: 調整する
- sole: 唯一の。発音は「ソール」
- offload: unload と同じ。本文中では「メモリの開放」を意味する
- stark: まさにそのもの
- retain: 保持する
- dedicated: 専門の
- as many as: 〜と同数の
- fairly-uncommon: かなりまれ
- indefinitely: 無期限に
- fire and forget child process: 「立ち上げたままほうっておかれる子プロセス」と訳すと意味がとおる
spawn「生む」の発音は "スポーン"。今まで "スパウン" と発音しててショック^^;