Linux Zombieプロセスのステータスの説明とクリーンアップ方法
5098 ワード
Linuxプロセスの状態
psのヘルプマニュアルでは、プロセスにいくつかのステータスが表示されます
man ps
D uninterruptible sleep (usually IO)
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped, either by a job control signal or because it is being traced
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
プロセス_exitが終了すると、プロセスが消費するメモリやその他のリソースが回収され、オペレーティングシステムのprocess tableに記録(PID、termination status、resource usage information)が保持されます.このとき、プロセスの状態はzombie/defunctです.
親プロセスはwaitpidシステム呼び出しを使用してzombie状態のサブプロセスを回収し、回収後のプロセスの情報はprocess tableから除去されます.Wikiの例
#include
#include
#include
int main(void)
{
pid_t pids[10];
int i;
for (i = 9; i >= 0; --i) {
pids[i] = fork();
if (pids[i] == 0) {
sleep(i+1);
_exit(0);
}
}
for (i = 9; i >= 0; --i)
waitpid(pids[i], NULL, 0);
return 0;
}
man 2 waitの解釈
A child that terminates, but has not been waited for becomes a "zom-
bie". The kernel maintains a minimal set of information about the zom-
bie process (PID, termination status, resource usage information) in
order to allow the parent to later perform a wait to obtain information
about the child. As long as a zombie is not removed from the system
via a wait, it will consume a slot in the kernel process table, and if
this table fills, it will not be possible to create further processes.
If a parent process terminates, then its "zombie" children (if any) are
adopted by init(8), which automatically performs a wait to remove the
zombies.
zombieプロセスの親プロセスがterminateされた場合、zombieプロセスはinitプロセスによって引き継がれ、initプロセスもzombieにあるプロセスを非同期で呼び出すwait回収を呼び出す.
いつZombie状態に入りますか
前に説明したように、プロセスexit後、zombie状態に入ります.その後、親プロセスはwaitpid呼び出しによりzombie状態のプロセスを回収します.zombieステータスプロセスの親プロセスがterminateされると、回収されていないzombieプロセスがinitに引き継がれ、initはwaitpidを呼び出してzombieサブプロセスを回収します.
なお、POSIX.1-2001標準のシステム、SIGCHLD to SIG_の設定を許可するIGNは、waitによってzombieサブプロセスを回収する必要がない.forkのサブプロセスプロセスはzombie状態に入らないため、exit後にprocess tableに情報は保持されません.
On modern UNIX-like systems (that comply with SUSv3 specification in this respect), the following special case applies: if the parent explicitly ignores SIGCHLD by setting its handler to SIG_IGN (rather than simply ignoring the signal by default) or has the SA_NOCLDWAIT flag set, all child exit status information will be discarded and no zombie processes will be left
POSIX.1-1990 disallowed setting the action for SIGCHLD to SIG_IGN.
POSIX.1-2001 allows this possibility, so that ignoring SIGCHLD can be
used to prevent the creation of zombies (see wait(2)). Nevertheless,
the historical BSD and System V behaviors for ignoring SIGCHLD differ,
so that the only completely portable method of ensuring that terminated
children do not become zombies is to catch the SIGCHLD signal and per-
form a wait(2) or similar.
Zombieステータスのプロセスをクリーンアップする方法
zombieプロセスの親プロセスによりwaitpid呼び出しを開始し、process table内の対応するサブプロセスの情報をクリーンアップします.親プロセスが処理されていない場合は、SIGCHLD信号を手動で開始し、処理させることができます.
kill -SIGCHLD $(ps -A -ostat,ppid | awk '/[zZ]/{print $2}')
この信号を送るのがまだだめなら、parentプロセスがこの信号を処理していない可能性があります.親プロセスも乾かして、initにzombieプロセスを回収させます.
掃除しないと何か危険がある
zombieプロセスはprocess tableのslotを占有し、非常に多くのzombieがある場合、最終的にはprocess table slotがいっぱいになり、システムが新しいプロセスを作成できない可能性があります.
リファレンス
http://stackoverflow.com/questions/16944886/how-to-kill-zombie-processhttps://manpages.debian.org/cgi-bin/man.cgi?query=wait&sektion=2https://en.wikipedia.org/wiki/Zombie_processhttp://unix.stackexchange.com/questions/11172/how-can-i-kill-a-defunct-process-whose-parent-is-inithttp://stackoverflow.com/questions/20535438/cant-cleanup-a-zombie-process-whose-parent-is-initman 2 exitman 2 waitman 7 signal
PostgreSQLが終了したサブプロセスをどのように処理するか
waitpidの影も見えます
src/backend/postmaster/postmaster.c: pqsignal(SIGCHLD, reaper); /* handle child termination */
/*
* Reaper -- signal handler to cleanup after a child process dies.
*/
static void
reaper(SIGNAL_ARGS)
{
int save_errno = errno;
int pid; /* process id of dead child process */
int exitstatus; /* its exit status */
PG_SETMASK(&BlockSig);
ereport(DEBUG4,
(errmsg_internal("reaping dead processes")));
while ((pid = waitpid(-1, &exitstatus, WNOHANG)) > 0)
{
...