Chinaunix首页 | 论坛 | 博客
  • 博客访问: 540048
  • 博文数量: 83
  • 博客积分: 6010
  • 博客等级: 准将
  • 技术积分: 1169
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-29 22:34
文章分类

全部博文(83)

文章存档

2011年(3)

2010年(29)

2009年(30)

2008年(21)

我的朋友

分类: LINUX

2009-03-11 11:32:07

昨天写了个简单的服务器程序http-serv,每次http-serv接受(accept)到一个请求时,都会创建一个新的子进程来响应该请求。于是每个子进程的退出,便需要处理,否则就是会出现僵死进程。
刚开始我是这样处理的:

static void
sig_child()
{
    waitpid(-1, NULL, 0);
}
[...]
signal(SIGCHLD, sig_child);

即用sig_child来处理SIGCHLD信号(进程退出时,父进程会收到该信号)。
刚开始这样并没问题,后来用了apach自带的ab进行了压力测试,就出现了僵死进程了。
想了好久,看了很多资料,最后发现sig_child这个函数有问题。这个函数的作用是每当有一个进程退出时,便会调用一次sig_child,sig_child便会调用waitpid处理一个已退出的子进程。但是假如程序正在sig_child里面,这时又有另外一个子进程退出了,这时该怎么处理呢?处理的方法应该是不会有另外一个sig_child响应,于是这时便有2个子进程退出了,但是sig_child只能处理一个,于是便有一个退出的子进程成了僵死进程了。

于是把sig_child改成:

static void
sig_child()
{
    while (waitpid(-1, NULL, 0) > 0);
}

这样假如程序正在sig_child里面,这时又有另外n个子进程退出了,由于用了while,于是sig_child便会将所以退出的子进程“一网打尽”。

这是一种处理僵死进程的方法,另外还有2种:
signal(SIGCHLD, SIG_IGN);
忽略SIGCHLD信号,父进程不需要处理,直接把退出的子进程推给init进程处理。

struct sigaction    sa;
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_NOCLDWAIT;
sigemptyset(&sa.sa_mask);
if (sigaction(SIGCHLD, &sa, NULL) < 0) {
    exit(-1);
}
第3种的机制跟第2种的机制是一样的,只是调用的接口不同,这里不再累诉。
阅读(1185) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~