首先介绍一下什么是僵死进程

  int main()
  {
      int n = 0;
      char *s = NULL;
 
      pid_t pid = fork();
      assert(pid != -1);
  
      if(pid == 0)
      {
          n = 3;
          int i = 0;
          for(; i < n; i++)
          {
              sleep(1);
              printf("child running\n");
          }
      }
      else
      {
          n = 7;
          int i = 0;
          for(; i < n; i++)
          {
              sleep(1);
              printf("parent running\n");
          }
      }
}

此时程序运行后,在子程序结束后,父进程尚且没有完成,此时查看一下进程信息,可以得到
图片描述
可以看到两个signalttt进程,其中子程序的signalttt进程已经处于defunct状态,此时子进程已经代码执行完毕,但是这个进程并没有终止,这就对CPU的进程资源造成了很多的浪费,如果说短时间内产成了大量的僵死进程,那么此时因为进程号等信息占用,此时不能创建新的进程

为什么会出现僵死进程呢?

我们来改一下代码:

int main()
{
int n = 0;
    char *s = NULL;
    if(pid == 0)
    {
       n = 7;
       int i = 0;
       for(; i < n; i++)
       {
          sleep(1);
          printf("child running\n");
       }
     }
     else
     {
        n = 3;
         int i = 0;
         for(; i < n; i++)
         {
            sleep(1);
            printf("parent running\n");
         }
      }
}

再次在运行途中查看ps
图片描述
图片描述
此时并没有和之前一样出现僵死进程,而我们仅仅是将子进程改的运行的时间比父进程长了一些,然后再次查看时候,发现僵死进程就消失了???
所以我们可以得到条件,僵死进程中,父进程一定要“活得久”~


这里本质上是因为,在Linux系统中,进程是有父子关系的,从init进程开始展开,是一个大的进程树,而子进程的结束都会由子进程向它的父进程发送一个信号(SIGCHLD),而此时如果父进程在运行中没有获取子进程的退出码,这样就出现了僵死进程

关于僵死进程的处理

  1. 在Linux系统中有一个特殊的处理方法,signal(SIGCHLD,SIG_IGN);子进程在结束时候会向父进程发送一个子进程结束的信号,我们调用signal函数去忽略掉这个信号,那么这时候子进程就会变成了孤儿进程,会自动的被init接收处理,init进程会在进程表中挨个查找孤儿进程,也就是说,进程表越大那么这个过程造成的资源占用也就越多

  2. 也可以在父进程中用wait();函数,这样在执行到这句时,父进程会等待到子进程结束后,但是这句会造成父进程的挂起

  3. 同样的,也可以用signal(SIGCHLD,fun);去实现一个处理子进程信号的函数,让父进程接收到信号之后,调用wait()将子进程结束掉

  4. 还有一种特殊的是利用两次fork(),这样父进程在第一次创建的子进程1中,再次创建一个子进程2,子进程2负责执行子进程的工作,而子进程1只做一件事件--------wait(子进程2);专心致志等待子进程2结束,这样就处理了wait导致的进程挂起的问题

`


且行且歌_C
62 声望8 粉丝

逝者如斯夫,不舍昼夜