博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
服务器进程为何通常fork()两次
阅读量:7223 次
发布时间:2019-06-29

本文共 1545 字,大约阅读时间需要 5 分钟。

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

孤儿进程

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

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

僵尸进程

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

     

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

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

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

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

两次fork()技法

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

《UNIX环境高级编程》(下载见)这本书里提供了两次fork的一个例子,代码如下:

  1. int main(void)  
  2. {  
  3.     pid_t        pid;  
  4.   
  5.     if ( (pid = fork()) < 0)  
  6.           err_sys("fork error");  
  7.     else if (pid == 0)   
  8.         {                /* first child */  
  9.            if ( (pid = fork()) < 0)  
  10.                         err_sys("fork error");  
  11.            else if (pid > 0)  
  12.                  exit(0);        /* parent from second fork == first child */  
  13.   
  14.                 /* We're the second child; our parent becomes init as soon 
  15.                    as our real parent calls exit() in the statement above. 
  16.                    Here's where we'd continue executing, knowing that when 
  17.                    we're done, init will reap our status. */  
  18.   
  19.             sleep(2);  
  20.             printf("second child, parent pid = %d\n", getppid());  
  21.             exit(0);  
  22.         }  
  23.   
  24.     if (waitpid(pid, NULL, 0) != pid)        /* wait for first child */  
  25.             err_sys("waitpid error");  
  26.   
  27.         /* We're the parent (the original process); we continue executing, 
  28.            knowing that we're not the parent of the second child. */  
  29.   
  30.     exit(0);  
  31. }  

理所当然,第二个子进程的父进程是进程号为1的init进程。

 一言以蔽之,两次fork()是为了防止系统中产生僵尸进程。 

转载于:https://www.cnblogs.com/tianlangshu/p/5200049.html

你可能感兴趣的文章
Linux运维常见面试题之精华收录
查看>>
Open Source的一些网站,自己收集来的
查看>>
导入ubuntu虚机配置,基于XEN4.0
查看>>
Script:收集UNDO诊断信息
查看>>
jmeter连接数据库-华山
查看>>
opencv 源码编译
查看>>
将旧硬盘的内容克隆到新硬盘
查看>>
Linux文件管理类命令之rm
查看>>
如何在Kubernetes中暴露服务访问
查看>>
NTP常见问题和解决方案&配置文件详解
查看>>
crontab计划任务补充知识
查看>>
数据库备份
查看>>
独家 | 图灵奖得主Raj Reddy:通用AI还很遥远,人类将成宠物
查看>>
java中自动生成XML文件
查看>>
Docker 数据卷,数据卷容器详细介绍
查看>>
VS2015编译Live555流媒体服务器
查看>>
依赖属性之“风云再起”三
查看>>
利用K8S技术栈打造个人私有云(连载之:K8S资源控制)
查看>>
mysql内存过高解决办法
查看>>
CentOS7 Ceph RBD CephFS 存储
查看>>