孤児プロセスとゾンビプロセスの違い

ゾンビプロセス(defunct)と孤児プロセスの違いを解説。PIDの枯渇リスク・psコマンドによる確認手順・killの方法、親プロセスとwaitシステムコールの仕組みをDockerコンテナの文脈も交えて紹介します。

Read in: en
孤児プロセスとゾンビプロセスの違い

概要

Dockerを触っていたらorphan(孤児の意)というプロセスの存在を知ったのでゾンビプロセスとの違いを調べてみた。

ゾンビプロセスとは

ゾンビプロセスとは、処理が終了した子プロセスがプロセステーブルに残り、親プロセスによるwait()システムコールを待っている状態のプロセスである。

Linuxでは、子プロセスが終了しても、親プロセスがwait()(またはwaitpid())を呼び出して終了ステータスを受け取るまで、プロセスの情報はプロセステーブルに保持される。この状態を「ゾンビ状態(defunct)」と呼ぶ。

特徴

ゾンビプロセスの確認方法

# ps auxでstatがZのもの、またはコマンド末尾がdefunctのもの
ps aux | grep defunct

# もしくは
ps -ef | grep defunct

ゾンビプロセスのkill

ゾンビプロセス自体は終了済みのため、killコマンドは効かない。親プロセスがwait()を呼び出すか、親プロセス自体をkillすることで解消される。親プロセスがkillされると、孤児プロセスがinitに引き取られてwaitが行われ、プロセステーブルから削除される。

# 親プロセスのPIDを確認(PPIDの欄)
ps -ef | grep defunct

# 親プロセスをkill
kill -9 <親プロセスのPID>

孤児プロセス

孤児プロセスとは、親プロセスがwait()を呼ばずに終了してしまったことで、親を失ったプロセスのことである。

Linuxでは、親プロセスが先に終了した場合、孤児プロセスはinitプロセス(PID: 1)またはサブリーパー(Dockerならtiniなど)に引き取られる。initプロセスが里親となり、定期的にwait()を呼んでゾンビ状態を解消する。

特徴

孤児プロセスの確認方法

# PPIDが1のプロセスのうちrootでないものを表示
ps -elf | head -1; ps -elf | awk '{if ($5 == 1 && $3 != "root") {print $0}}' | head

孤児プロセスのkill

kill <PID>

ゾンビプロセスと孤児プロセスの対比

項目 ゾンビプロセス 孤児プロセス
状態 終了済み(defunctとして残存) 実行中
リソース消費 なし(PIDのみ保持) あり
親プロセス 存在するがwait()待ち 存在しない(initが引き取る)
問題のリスク PID枯渇 リソース消費続行
解消方法 親がwait()するか、親をkill killコマンドで終了

Dockerにおける注意点

Dockerコンテナ内のPID 1プロセスが通常のアプリ(nodepython等)の場合、signal処理やwait()をデフォルトでは行わないため、ゾンビプロセスが蓄積しやすい。docker run--initフラグを付けるか、tiniなどのinitプロセスマネージャーを使用することが推奨される。

# docker-compose.ymlでの設定
services:
  app:
    image: myapp
    init: true  # tiniをPID 1として使用

参考

Tags: UNIX プロセス
Share: 𝕏 Post Facebook Hatena
✏️ View source / Discuss on GitHub
☕ サポート

このブログを応援していただける方は、以下からサポートをお願いします。いただいたサポートはブログ運営・技術研鑽に活用します。


関連記事