您的位置:首页 > 其它

避免产生僵尸进程的N种方法(zombie process)

2012-09-10 22:28 411 查看

认识僵尸进程

1、如果父进程先退出

子进程自动被 init 进程收养,不会产生僵尸进程

 

2、如果子进程先退出

2.1 父进程 wait() 处理,则僵尸进程会被父进程清理

2.2 如果父进程不用 wait() 处理,则僵尸进程会在父进程退出之前一直存在。当然,父进程退出后,僵尸子进程会被 init 收养,init 进程会自动调用 wait() 处理。但是对于处理网络请求的服务器进程来说,父进程可能会一直存在,子进程处理完任务就退出,这种情况下会产生很多僵尸进程,这种场景就需要对僵尸进程的处理提高警惕了。

避免产生僵尸进程的5种方法

1、推荐方法:fock twice, 用孙子进程去完成子进程的任务(注意这种方法的使用情景)(http://blog.csdn.net/duyiwuer2009/article/details/7948040

2、wait(), 但是会使父进程阻塞

3、signal(SIGCHLD,SIG_IGN), 并不是所有系统都兼容

4、sigaction + SA_NOCLDWAIT, 并不是所有系统都兼容

5、推荐方法:在signal handler中调用 waitpid (下面的例子能说明用 waitpid 而不用 wait的原因),这样父进程不用阻塞

注意:每一种方法都有它适用的场合,比如方法 5 适用于 one-request-one-process 的网络服务器程序,而方法 1 则不适合。

关于对处理SIGCHLD或SIGCLD的讨论,APUE 10.7(http://infohost.nmt.edu/~eweiss/222_book/222_book.html) 是最权威最经典的,不过可能由于书出得较早,考虑了太多老系统,当时的系统对信号的处理还不是很完善,使得书中对这个问题的讨论显得相当复杂,但对于现在的系统,我们可以简化许多。

方法4的代码:

#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
pid_t pid;
struct sigaction sa;

/* prevent zombies */
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_NOCLDWAIT;
if (sigaction(SIGCHLD, &sa, NULL) == -1)
{
perror("sigaction");
exit(1);
}

if( (pid = fork()) < 0 )
{
exit(1);
}
else if(pid == 0)
{
sleep(10);
exit(0);
}
sleep(20);

return 0;
}
笔者所用系统的内核版本是2.6.38-8,方法3和方法4都支持

方法5的代码:

/**
* Final (correct) version of sig_chld function that calls waitpid.
*
* UNIX Network Programming Volume 1, Third Edition, 5.9(Handling 'SIGCHLD' Signals) and 5.10
*/
void sig_chld(int signo)
{
pid_t	pid;
int stat;

while ( (pid = waitpid(-1, &stat, WNOHANG)) > 0 )
{
printf("child %d terminated\n", pid);
}
return;
}
Establishing a signal handler and calling wait from that handlerare insufficient for preventing zombies. The problem is that if five signals are generated before the signal handler is executed, the signal handler
is executed only one time becauseUnix signals are normally not queued(这种情况下只会产生一次"SIGCHLD"信号).

In this case, the signal handler is executed once, leaving four zombies.

The correct solution is to call waitpid
instead of wait, and we must specify theWNOHANGoption: This tells waitpid not to block if there are running children that have not yet terminated.

【参考资料】

UNIX Network Programming Volume 1, Third Edition, 5.9(Handling 'SIGCHLD' Signals) and 5.10

http://topic.csdn.net/u/20090911/16/5860C371-DBF9-440A-851B-C6AD26B6E480.html

http://baike.baidu.com/view/758736.htm

线程和进程的分离,http://blog.chinaunix.net/space.php?uid=317451&do=blog&id=92626

How do I get rid of zombie processes that persevere, http://www.faqs.org/faqs/unix-faq/faq/part3/section-13.html

http://www.ccur.com/isdfaq/How_do_I_avoid_creating_zombies.txt
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  signal struct 任务 null c