欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

孤儿进程和僵尸进程

发布时间:2025/7/14 编程问答 38 豆豆
生活随笔 收集整理的这篇文章主要介绍了 孤儿进程和僵尸进程 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

前几天接到某互联网公司的电话面试,面试官问我两次fork()的作用,我一头雾水,说不知道。知识面还是太窄了。下面就总结下两次fork()的作用。

 

首先,要了解什么叫僵尸进程,什么叫孤儿进程,以及服务器进程运行所需要的一些条件。两次fork()就是为了解决这些相关的问题而出现的一种编程方法。

 孤儿进程

        孤儿进程是指父进程在子进程结束之前死亡(return 或exit)。如下图1所示:

图1  孤儿进程

但是孤儿进程并不会像上面画的那样持续很长时间,当系统发现孤儿进程时,init进程就收养孤儿进程,成为它的父亲,child进程exit后的资源回收就都由init进程来完成。

 

僵尸进程

         僵尸进程是指子进程在父进程之前结束了,但是父进程没有用wait或waitpid回收子进程。如下图所示:

     

图2   僵尸进程

         父进程没有用wait回收子进程并不说明它不会回收子进程。子进程在结束的时候会给其父进程发送一个SIGCHILD信号,父进程默认是忽略SIGCHILD信号的,如果父进程通过signal()函数设置了SIGCHILD的信号处理函数,则在信号处理函数中可以回收子进程的资源。

      事实上,即便是父进程没有设置SIGCHILD的信号处理函数,也没有关系,因为在父进程结束之前,子进程可以一直保持僵尸状态,当父进程结束后,init进程就会负责回收僵尸子进程。

      但是,如果父进程是一个服务器进程,一直循环着不退出,那子进程就会一直保持着僵尸状态。虽然僵尸进程不会占用任何内存资源,但是过多的僵尸进程总还是会影响系统性能的。黔驴技穷的情况下,该怎么办呢?

         这个时候就需要一个英雄来拯救整个世界,它就是两次fork()技法。

两次fork()技法

         两次fork()的流程如下所示:

图3    两次fork的控制流

       如上图3所示,为了避免子进程child成为僵尸进程,我们可以人为地创建一个子进程child1,再让child1成为工作子进程child2的父进程,child2出生后child1退出,这个时候child2相当于是child1产生的孤儿进程,这个孤儿进程由系统进程init回收。这样,当child2退出的时候,init就会回收child2的资源,child2就不会成为孤魂野鬼祸国殃民了。

 

   <unix环境高级编程>这本书里提供了两次fork的一个例子,代码如下:

[cpp] view plaincopy
  • int main(void)  
  • {  
  •     pid_t        pid;  
  •   
  •     if ( (pid = fork()) < 0)  
  •           err_sys("fork error");  
  •     else if (pid == 0)   
  •         {                /* first child */  
  •            if ( (pid = fork()) < 0)  
  •                         err_sys("fork error");  
  •            else if (pid > 0)  
  •                  exit(0);        /* parent from second fork == first child */  
  •   
  •                 /* We're the second child; our parent becomes init as soon 
  •                    as our real parent calls exit() in the statement above. 
  •                    Here's where we'd continue executing, knowing that when 
  •                    we're done, init will reap our status. */  
  •   
  •             sleep(2);  
  •             printf("second child, parent pid = %d\n", getppid());  
  •             exit(0);  
  •         }  
  •   
  •     if (waitpid(pid, NULL, 0) != pid)        /* wait for first child */  
  •             err_sys("waitpid error");  
  •   
  •         /* We're the parent (the original process); we continue executing, 
  •            knowing that we're not the parent of the second child. */  
  •   
  •     exit(0);  
  • }  
  •        理所当然,第二个子进程的父进程是进程号为1的init进程。  
  •          一言以蔽之,两次fork()是人为地创建一个工作子进程的父进程,然后让这个人为父进程退出,之后工作子进程就由init回收,避免了工作子进程成为僵尸进程。

    转载于:https://www.cnblogs.com/cobbliu/archive/2012/03/10/2388565.html

    总结

    以上是生活随笔为你收集整理的孤儿进程和僵尸进程的全部内容,希望文章能够帮你解决所遇到的问题。

    如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。