地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

ゾンビプロセスを作る

Cで作るゾンビプロセス

プロセスはLinuxソースコード上ではタスクやスレッドとして実装されている。 Linuxにおけるプロセスは主だった情報だと下記を保持している。

①プロセス管理情報

-> レジスタの退避領域:プロセス切替えの時レジスタ(PCやSP)を退避するための領域

-> プロセスの属性:プロセスIDや所有者など

-> 統計情報:プロセスが動いた時間

②メモリ管理情報

③ファイル管理情報

上に上げたもの以外にもたくさんの情報を持っている。 (細かく見ていく気力はなかったのでまたいつか。。。)

// include/linux/sched.h

struct task_struct {
    volatile long state;  /* -1 unrunnable, 0 runnable, >0 stopped */
    struct thread_info *thread_info;
    atomic_t usage;
    unsigned long flags;  /* per process flags, defined below */
    
    int prio, static_prio;
    struct list_head run_list;
    prio_array_t *array;

    struct list_head tasks;
    struct mm_struct *mm, *active_mm;
    struct task_struct *real_parent; /* real parent process (when being debugged) */
    struct task_struct *parent;    /* parent process */
    struct thread_struct thread;
    struct fs_struct *fs;
    struct files_struct *files;
    struct signal_struct *signal;
    struct sigpending pending;
};

プロセスは主に下記の手順で生成される

① プロセステーブル内の空き領域を探す

② プロセス構造体を割り当てる

③ プロセス構造体の初期化(プロセスID決め、データ・スタック・コード領域の大きさを決め割り当て)

④ プロセス実行

ゾンビプロセス

この記事ではその中でもゾンビプロセスについて書いてみた。 ゾンビプロセスとは親プロセスがwaitで子の終了ステータスを取得しない間、子プロセスはゾンビ状態となる。

早速作ってみる

プロセスの生成にはおなじみのfork(2)システムコールを使用。 親プロセスはfork後にsleepに入り子プロセスは生成後にすぐに終了するような実装。

#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
   pid_t pid;
   struct sigaction sa;
   sa.sa_handler = SIG_IGN;
   sa.sa_flags = SA_NOCLDWAIT;
   if (sigaction(SIGCHLD, &sa, NULL) == -1) {
       exit(1);
   }

   pid = fork();
   if (pid == 0 )
   {
       /* 子プロセス */
       printf("This is child process.\n");
       exit(0);
   }
   /* 親プロセス */
   sleep(10);
   return 0;
}

プロセスの状態を確認すると

[root@cnt08 ~]# ps aux | grep python3
root     32557  0.0  0.2  23044  7908 pts/1    S+   12:07   0:00 python3 a.py
root     32558  0.0  0.0      0     0 pts/1    Z+   12:07   0:00 [python3] <defunct> #! ステータスがZとなっている
root     32611  0.0  0.0  10284  1060 pts/2    S+   12:08   0:00 grep --color=auto python3

ゾンビプロセスに限らずプロセスは終了時に下記の手順を取る。

① オープンしてたファイルをすべて閉じる

② プロセスが使用してたメモリ領域の解放

③ プロセス構造体を解放

④ プロセステーブルのエントリ解放

⑤ プロセスの終了

実装を細かく追うならこの辺。

参考記事

www.coins.tsukuba.ac.jp

k-onishi.hatenablog.jp