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
ゾンビプロセスに限らずプロセスは終了時に下記の手順を取る。
① オープンしてたファイルをすべて閉じる
② プロセスが使用してたメモリ領域の解放
③ プロセス構造体を解放
④ プロセステーブルのエントリ解放
⑤ プロセスの終了
実装を細かく追うならこの辺。