在上篇博客提到的SIGCHLD信号就是由内核在任何一个进程终止时发给它的父进程的一个信号。那我们怎么处理僵死进程呢?
处理僵死进程
我们显然不愿意存留僵死进程。它占用内核空间,最终可能导致我们耗尽进程资源,无论何时我们fork子进程都要wait它们,以防止它们变成僵死进程。为此我们建立一个捕获SIGCHLD信号的信号处理函数,在函数体中我们调用wait。
wait与waitpid
waitpid比wait更好用。我们通过一个案例说明。
(1)我们修改客户端程序,客户与服务器建立5个连接。建立多个连接的目的是从并发服务器上派生多个子进程。调用str_cli函数时仅用第一个连接。
(2)所有客户终止时,所有打开的描述符由内核自动关闭(仅调用exit),且所有5个连接基本在同一时刻终止。这就引发了5个FIN,每个连接一个,它们反过来时服务器的5个子进程基本在同一时刻终止。这又导致差不多有5个SIGCHLD信号递交给父进程。
(3)建立一个信号处理函数并在其中调用wait函数并不足以防止出现僵死进程。
代码实现
void handle_sigchld(int sig)
{
// wait(NULL);//2只等待第一个进程退出,就返回
while(waitpid(-1,NULL,WNOHANG>0))
;
}