1. 概念:
在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵尸进程。补救办法是杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程.
2. 本质:
所谓以root身份也不能杀死僵尸进程,其实只是用户态的感觉。真正原因是这个进程在内核看来已经结束了,你不能杀死一个死人,不是吗。内核维护了一些状态信息,等待其父进程获取这些状态信息,除非父进程明确表示它不想获取这些状态信息。
3. 处理:
显式忽略SIGCHLD信号是指类似这样的代码:
signal( SIGCHLD, SIG_IGN );
安装SIGCHLD信号句柄是指类似这样的代码:
static void on_sigchld ( int signo )
{
pid_t pid;
int status;
while ( ( pid = waitpid( -1, &status, WNOHANG ) ) > 0 )
{
/*
* 演示用,不推荐在信号句柄中使用fprintf()
*/
fprintf( stderr, "child terminated", ( unsigned int )pid );
}
return;
} /* end of on_sigchld */
... ...
signal( SIGCHLD, on_sigchld );
当然,我们不建议使用signal(),应该使用sigaction()。
在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵尸进程,无法正常结束,此时即使是root身份kill -9也不能杀死僵尸进程。补救办法是杀死僵尸进程的父进程(僵尸进程的父进程必然存在),僵尸进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵尸进程.
2. 本质:
所谓以root身份也不能杀死僵尸进程,其实只是用户态的感觉。真正原因是这个进程在内核看来已经结束了,你不能杀死一个死人,不是吗。内核维护了一些状态信息,等待其父进程获取这些状态信息,除非父进程明确表示它不想获取这些状态信息。
3. 处理:
显式忽略SIGCHLD信号是指类似这样的代码:
signal( SIGCHLD, SIG_IGN );
安装SIGCHLD信号句柄是指类似这样的代码:
static void on_sigchld ( int signo )
{
pid_t pid;
int status;
while ( ( pid = waitpid( -1, &status, WNOHANG ) ) > 0 )
{
/*
* 演示用,不推荐在信号句柄中使用fprintf()
*/
fprintf( stderr, "child terminated", ( unsigned int )pid );
}
return;
} /* end of on_sigchld */
... ...
signal( SIGCHLD, on_sigchld );
当然,我们不建议使用signal(),应该使用sigaction()。
Link URL: http://hyyuanqiang.blog.163.com/blog/static/59415137200932811756154
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12165911/viewspace-604323/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12165911/viewspace-604323/