ゾンビプロセスって?
Rev.1を表示中。最新版はこちら。
初心者のころゾンビプロセスって、名前からしてものすごく気味わるく、システム上に絶対あってはならないものとばかりに、psで探し出してはkill,killしていたものでした。で、ゾンビ状態っていうのはどのようなものか今もって分かりません。そこでその謎をさぐるべくwaitを追ってみました。親プロセスのwaitはdo_wait関数が呼ばれ、子プロセスからのシグナルを待ち受けるようwaitキュー追加し、すべての子プロセスからシグナルは無いかチェックします。そのチェックはwait_consider_task関数で行い、もしそのシグナルがEXIT_ZOMBIE(ゾンビ状態)のプロセスだと、wait_task_zombie関数で処理されます。
wait_task_zombie関数で、子プロセスをEXIT_DEAD状態に変更したのち、このプロセスに関するCPU情報等の統計情報を収集して、最後にタスク構造体を解放しているようでした。
結論としては、ゾンビ状態とは親プロセスが子プロセスのCPU等の統計情報を収集するための一時的な状態のことを言うようです。
static long do_wait(enum pid_type type, struct pid *pid, int options, { DECLARE_WAITQUEUE(wait, current); struct task_struct *tsk; int retval; waitキューに接続 add_wait_queue(¤t->signal->wait_chldexit,&wait); repeat: retval = -ECHILD; if ((type < PIDTYPE_MAX) && (!pid || hlist_empty(&pid->tasks[type]))) goto end; ・ tsk = current; do { ・ 自プロセス配下についてチェック int tsk_result = do_wait_thread(tsk, &retval, type, pid, options, infop, stat_addr, ru); ・ tsk = next_thread(tsk); BUG_ON(tsk->signal != current->signal); } while (tsk != current);
static int do_wait_thread(struct task_struct *tsk, int *notask_error, { struct task_struct *p; tsk配下の子および兄弟プロセスについてチェック list_for_each_entry(p, &tsk->children, sibling) { if (!task_detached(p)) { int ret = wait_consider_task(tsk, 0, p, notask_error, type, pid, options, infop, stat_addr, ru); if (ret) return ret; } } return 0; }
static int wait_consider_task(struct task_struct *parent, int ptrace, { int ret = eligible_child(type, pid, options, p); if (!ret) return ret; ・ ゾンビだとwait_task_zombieを呼び出し if (p->exit_state == EXIT_ZOMBIE && !delay_group_leader(p)) return wait_task_zombie(p, options, infop, stat_addr, ru); ・
static int wait_task_zombie(struct task_struct *p, int options, { unsigned long state; int retval, status, traced; pid_t pid = task_pid_vnr(p); ゾンビプロセスをEXIT_ZOMBIEからEXIT_DEADに変更 state = xchg(&p->exit_state, EXIT_DEAD); if (state != EXIT_ZOMBIE) { BUG_ON(state != EXIT_DEAD); return 0; } 統計情報の取得 if (likely(!traced)) { struct signal_struct *psig; struct signal_struct *sig; ・ psig->cutime = cputime_add(psig->cutime, cputime_add(p->utime, cputime_add(sig->utime, sig->cutime))); ・ psig->cnvcsw += p->nvcsw + sig->nvcsw + sig->cnvcsw; ・ } ・ タスク構造体の解放 if (p != NULL) release_task(p);