3

私のメインプロセスは子プロセスを生成します。メインプロセスが強制終了された場合、子にはppid 1が割り当てられます。子が終了すると、initがこの子に対してwait()を呼び出さなかったため、ゾンビになります。この状況を回避する方法はありますか?

4

2 に答える 2

8

init wait()継承するプロセスを呼び出します。ゾンビは、子が終了したが、親はまだ存在しているが、まだ終了コードを取得していない場所にのみ存在する必要があります。マンページからinit

initシステム上のすべてのプロセスの親であり、カーネルによって実行され、他のすべてのプロセスを開始する責任があります。それは、自然の親が死んだすべてのプロセスの親であり、死んだときにそれらを刈り取る責任があります。

孤児(彼らはまだ生きていて、彼らの親は死んでいるので、彼らは養子縁組されていinitます)とゾンビ(彼らは死んでいますが、彼らの親は生きていて、まだ彼らを刈り取っていません)を区別する必要があります。

孤児は、退出した後、刈り取る前の非常に短い期間ゾンビになりinitますが、この期間は誰も気付かないほど十分に小さいはずです。実際、すべての既存のプロセス(おそらくinitそれ自体を除く)はこの短いゾンビフェーズを通過します。親が気付くほど迅速に刈り取らない場合のみです。


init乳幼児死亡( )ハンドラーの実際のコードSIGCHLDは次のようになります(私のコメント):

void chld_handler (int sig) {
    CHILD  *ch;
    int    pid, st;
    int    saved_errno = errno;

    while ((pid = waitpid(-1, &st, WNOHANG)) != 0) { // << WAIT done here
        if (errno == ECHILD) break;
        for (ch = family; ch; ch = ch->next) {
            if (ch->pid == pid && (ch->flags & RUNNING)) {
                INITDBG (L_VB, child_handler: marked %d as zombie", ch->pid);
                ADDSET (got_signals, SIGCHLD);
                ch->exstat = st;
                ch->flags |= ZOMBIE;                 // Set to zombie here.
                if (ch->new) {
                    ch->new->exstat = st;
                    ch->new->flags |= ZOMBIE;
                }
                break;
            }
        }
        if (ch == NULL) {
            INITDBG (L_VB, "chld_handler: unknown child %d exited.", pid);
        }
    }
    errno = saved_errno;
}

そして、後でメインループ(シグナルハンドラではない)で、としてマークされたプロセステーブル内のすべてのプロセスZOMBIEがクリーンアップされます。

if (ISMEMBER (got_signals, SIGCHLD)) {
    INITDBG(L_VB, "got SIGCHLD");
    /* First set flag to 0 */
    DELSET(got_signals, SIGCHLD);

    /* See which child this was */
    for (ch = family; ch; ch = ch->next) {
        if (ch->flags & ZOMBIE) {                    // ZOMBIE detected here
            INITDBG (L_VB, "Child died, PID= %d", ch->pid);
            ch->flags &= ~(RUNNING|ZOMBIE|WAITING);  // And cleared here.
            if (ch->process[0] != '+') {
                write_utmp_wtmp ("", ch->id, ch->pid, DEAD_PROCESS, NULL);
            }
        }
    }
}
于 2012-12-14T00:32:55.493 に答える
0

プログラムの最後に1つのwait(NULL)ステートメントを配置して、親と子が両方とも実行を完了し、どちらからもゾンビプロセスにならないように、お互いを待機します。

于 2012-12-15T15:44:12.070 に答える