ゾンビプロセスをなかなか見ることができない理由

新しいプロセスを作成するとき、Linuxではfork()を使用します。
fork()から親プロセスは子プロセスを生成し、子プロセスで実際に実行しようとするプログラムをexec()を通じて実行します。

子プロセスがexit()を呼び出して終了すると、親プロセスはwaitpid()を明示的に呼び出して、この子プロセスのexit値を取得する必要があります。

子プロセスがexit()を呼び出しても、親プロセスがwaitpid()で子プロセスのPIDを回収(reaping)しなかった場合、この子プロセスはゾンビ(zombie)状態になります。

$ ps -e -o pid,stat,comm | grep a.out
32499 S+   a.out
32500 Z+   a.out <defunct>

しかし、このようなゾンビプロセスはなかなか見ることができません。
通常は親プロセスがwaitpidでうまく処理するように組まれているからです。

また、このようなゾンビプロセスが生じても、親プロセスが終了すると、カーネルはこのゾンビプロセスをinit(またはSystemd)プロセスの子として取り込みます。initやSystemdは定期的にwaitpid()を用いてゾンビプロセスを回避します。
https://en.wikipedia.org/wiki/Zombie_process 参照)

このようなことから、我々がゾンビプロセスを見ることができる状況は2つに限定されます。

  1. 親プロセスが生きた状態でありながら、明示的に子プロセスのwaitpidを呼び出せない場合
  2. systemdやinitが誤動作してゾンビプロセスを適切に回収できない場合

ゾンビを直接見てみたい方は下のコードをご利用ください。
コンパイルして実行し、5秒後にPSで該当のバイナリ状態を見れば確認できます。

#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main()
{
    int pid;
    int status;
    pid = fork();

    //signal(SIGCHLD, SIG_IGN);

    if (pid == 0)
    {
        sleep(5);
        printf("I will be back %d\n", getpid());
        exit(0);
    }
    else if(pid > 0)
    {
        printf("Im parent %d\n", getpid());
        printf("Press any key\n");
        getchar();
/*
        while(1)
        {
            printf("Im sleeping\n");
            sleep(1);
        }
*/
    }
    else
    {
        perror("fork error :");
    }
}

TOAST Meetup 編集部

TOASTの技術ナレッジやお得なイベント情報を発信していきます
pagetop