僵死进程(僵尸进程)
一、僵死进程产生的原因
用fork创建进程,子进程终止时,它与父进程之间还会保持联系,知道父进程也正常终止或者父进程调用wait才结束,所以进程表中子进程的表项不会立即释放,因为它的退出码还需要保存起来,以备父进程wait调用的时候使用。
子进程先于父进程结束,父进程没有获取子进程的退出码。
实验:
实验解析:
如果用 ./main &命令运行上面的程序,然后在子进程结束后父进程结束前使用ps命令,就会看到僵死进程产生: main <defunct>.
如果此时父进程异常终止,子进程将自动把PID为1的进程(init)作为自己的父进程,子进程就不是一个僵死进程了。
二、如何解决僵死进程
1、程序中显示的调用signal(SIGCHLD, SIG_IGN)来忽略SIGCHLD信号,这样子进程结束后,由内核来wait和释放资源。
2、对子进程的退出捕获它们的退出信号SIGCHLD。这样就可以释放它们的资源。父进程一般没工夫在那里守着,等着子进程的退出,所以,一般使用信号的方式来处理,在收到SIGCHLD信号的时候,在信号处理函数中调用(wait)waitpid() 操作来释放他们的资源。
代码示例:
void sig_chld(int signo)
{
pid_t pid;
int stat;
while((pid = waitpid(-1, &stat, WNOHANG)) > 0){
printf("child %d terminated\n", pid);
}
return;
}
然后在main()中,在fork语句的前面的某个地方设置子进程退出的信号处理函数,如下所示:
if(signal(SIGCHLD, sig_chld) == SIG_ERR)
{
fprintf(stderr, "signal error : %s\n", strerror(errno));
return 1;
}