Linux环境下僵死进程的产生及其避免

     在fork()/execve()过程中,假设子进程结束时父进程仍存在,而父进程fork()之前既没安装SIGCHLD/SIGCLD信号处理函数调用waitpid()等待子进程结束,又没有显式忽略该信号,则子进程成为僵死进程,无法正常结束,此时即使是root身份kill -9也不能杀死这类进程。补救办法是杀死僵尸进程的父进程(僵死进程的父进程必然存在),僵死进程成为"孤儿进程",过继给1号进程init,init始终会负责清理僵死进程。

产生僵死进程的程序:

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
int main()
{
   int i,pid;
   if((pid=fork())==0)//creat child pid
   {
      exit(0);//child pid exits,sending SIGCLD to parent pid
   }
   else
   {
     for(i=0;i<10;i++)
      sleep(5);
   }
}

程序编译执行后,子进程退出发送SIGCLD信号给父进程,而父进程没有处理此信号的动作,导致子进程无法正常结束。

执行程序zombie的同时,打开另一个终端执行ps aux会有如下的情况:

从结果中可以看出,此子进程状态为Z+,是僵死进程

如何避免僵死进程?途径有两种:1.父进程忽略SIGCLD信号;2.父进程捕捉SIGCLD信号,在信号处理函数中获取子进程退出状态。

第一种情况直接在原程序中添加signal(SIGCLD,SIG_IGN)即可;

下面讨论第二种情况,加入信号处理函数:

#include<stdio.h>
#include<stdlib.h>
#include<signal.h>
#include<unistd.h>
void handle_sigcld(int signo)
{
   int pid,status;
   pid=waitpid(-1,&status,0);//-1表示等待任何子进程
   printf("child process %d exit with %d\n",pid,status);
}

int main()
{
   int i,pid;
   //signal(SIGCLD,SIG_IGN);//忽略SIGCLD信号
   signal(SIGCLD,handle_sigcld);
   if((pid=fork())==0)//creat child pid
   {
      exit(0);//child pid exits,sending SIGCLD to parent pid
   }
   else
   {
     for(i=0;i<10;i++)
      sleep(5);
   }
}
程序安装信号处理函数handle_sigcld,当子进程结束时,触发信号处理函数,等待子进程结束。


你可能感兴趣的:(Linux环境下僵死进程的产生及其避免)