昨天写了个简单的服务器程序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种的机制是一样的,只是调用的接口不同,这里不再累诉。
阅读(1245) | 评论(0) | 转发(1) |