当前位置: 技术问答>linux和unix
忽略SIGCHLD信号能避免僵尸进程吗?
来源: 互联网 发布时间:2016-08-25
本文导语: 主程序要一直运行,会经常调用另一个程序,运行久了之后就看到很多僵尸进程,在网上看到有人说忽略SIGCHLD信号能避免僵尸进程,因为忽略SIGCHLD后僵尸进程会交给init管理,也有人说忽略SIGCHLD只会让僵尸进程越来越...
主程序要一直运行,会经常调用另一个程序,运行久了之后就看到很多僵尸进程,在网上看到有人说忽略SIGCHLD信号能避免僵尸进程,因为忽略SIGCHLD后僵尸进程会交给init管理,也有人说忽略SIGCHLD只会让僵尸进程越来越多。
麻烦各位说说你们的看法
麻烦各位说说你们的看法
|
这种方法,不是所有的操作系统都实现了。
前面的帖子有点问, 应该加一句:
void sig_chld(int signo)
{
pid_t pid;
int stat;
signal(SIGCHLD, &sig_chld);
while((pid = waitpid(-1, &stat, WNOHANG)) > 0) {
printf("child %d terminatedn", pid);
}
return;
}
int main(void)
{
int rc;
rc = 0;
signal(SIGCHLD, &sig_chld);
return (rc);
}
|
部分源自System V的Unix(比如AIX)的signal()函数保留了原始Unix的不可靠信号的语意:
信号被捕获后,信号处理自动被重置为SIG_DEF,就好像调用了signal(SIGCHLD, SIG_DEF)一样,
而且不会屏蔽正在处理的信号。
所以,需要在信号处理函数内的开始重新安装信号处理函数
当然这里也存在一个时间窗,在进入信号处理函数后,调用signal之前又收到信号的话,如果这个信号
的缺省行为是结束进程的话,进程可能会意外终止。
当然在这里,SIGCHLD的缺省行为不会终止进程,但是由于信号处理函数被重置,还会留下zombie,
POSIX 的sigaction就提供和可靠信号:
1. 从不重置信号处理为SIG_DEF, 除非特别设置。
2. 在信号处理函数执行期间,自动屏蔽正在处理的信号,除非特别设置。
|
当然不是,除非这些僵尸的父进程结束。
|
加上后,如果在进入信号处理函数和调用signal(SIGCHLD, &sig_chld);之间
又几个子进程结束,可能会留下几个zombie, 但是,一旦signal(SIGCHLD, &sig_chld);调用
结束,又有子进程结束的话,
while((pid = waitpid(-1, &stat, WNOHANG)) > 0)
将会清除上次这些zombie. 这样就基本消除了zombie产生的可能性。
最好使用sigaction 代替signal, 可以完美的保证在支持(sigaction + waitpid)不会留下zombie.
实际上很多Unix系统上zombie是进程的必经阶段,是给父进程机会查看子进程的退出状态。
sigaction + waitpid 完全可以可靠的清除zombie,不要把自己的工作留给系统去做。
使用fork的服务器服务程序,会不断产生子进程,子进程完成任务后会退出,如果不清除zombie,
会缓慢消耗系统资源的。
|
忽略SIGCHILD后, 僵死进程并不一定会被INIT处理, 如果进程的父进程不是INIT
|
避免产生僵尸进程的方法一般有:
1. fork两次,使得孙子进程的父亲为init,孙子进程去执行job
2. 制定自己的SIGCHLD信号处理函数,在这个信号处理函数中调用wait()
3. 通过sigaction系统调用指定信号SIGCHLD处理动作中的sa_flags为SA_NOCLDWAIT
1. fork两次,使得孙子进程的父亲为init,孙子进程去执行job
2. 制定自己的SIGCHLD信号处理函数,在这个信号处理函数中调用wait()
3. 通过sigaction系统调用指定信号SIGCHLD处理动作中的sa_flags为SA_NOCLDWAIT
|
避免僵尸进程要父进程wait子进程 或者直接把子进程由INIT进程管理
总归要有个进程收尸
你的父进程一直在(无法让子进程被INIT进程收养),而又不给子进程收尸就会产生了。
LS很全面了
总归要有个进程收尸
你的父进程一直在(无法让子进程被INIT进程收养),而又不给子进程收尸就会产生了。
LS很全面了
|
当父进程结束 这子进程就成了孤儿进程 INIT进程会领养 子进程结束就没了
这个只是在系统上有条记录,不占资源,等回收后连记录都没了。但是在有些调试状态会一直有
kill -9 PID可以杀掉 弄不好要有个记录 占用了一个进程ID而已,不碍事
这个只是在系统上有条记录,不占资源,等回收后连记录都没了。但是在有些调试状态会一直有
kill -9 PID可以杀掉 弄不好要有个记录 占用了一个进程ID而已,不碍事