如何防止僵尸进程?

如何防止僵尸进程?1 僵尸进程 僵尸进程是当子进程比父进程先结束 而父进程又没有回收子进程 释放子进程占用的资源 此时子进程将成为一个僵尸进程 如果父进程先退出 子进程被 init 接管 子进程退出后 init 会回收其占用的相关资源 2 产生原因 a 子进程结束后向父进程发出 SIGCHLD 信号 父进程默认忽略了它 b 父进程没有调用 wait 或 waitpid 函数来等待子进程的结束 c 网络原

1.僵尸进程:僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被init接管,子进程退出后init会回收其占用的相关资源。

2.产生原因:

a. 子进程结束后向父进程发出SIGCHLD信号,父进程默认忽略了它;

b. 父进程没有调用wait()或waitpid()函数来等待子进程的结束;

c. 网络原因有时会引起僵尸进程;

3. 危害

僵尸进程会占用系统资源,如果很多,则会严重影响服务器的性能;

4.如何防止僵尸进程

(1) 让僵尸进程成为孤儿进程,由init进程回收;(手动杀死父进程)

(2) 调用fork()两次;

(3) 捕捉SIGCHLD信号,并在信号处理函数中调用wait函数;

多进程编程之如何避免僵尸进程

1、两次fork()来避免僵尸进程      

   当我们只fork()一次后,存在父进程和子进程。这时有两种方法来避免产生僵尸进程:

    1)父进程调用waitpid()等函数来接收子进程退出状态;

    2)父进程先结束,子进程则自动托管到Init进程(pid = 1)。 

  考虑子进程先于父进程结束的情况:     

  • 若父进程未处理子进程退出状态,在父进程退出前,子进程一直处于僵尸进程状态。
  • 若父进程调用waitpid()(这里使用阻塞调用确保子进程先于父进程结束)来等待子进程结束,将会使父进程在调用waitpid()后进入睡眠状态,只有子进程结束父进程的waitpid()才会返回。 如果存在子进程结束,但父进程还未执行到waitpid()的情况,那么这段时期子进程也将处于僵尸进程状态。

      由此,可以看出父进程与子进程有父子关系,除非保证父进程先于子进程结束或者保证父进程在子进程结束前执行waitpid(),子进程均有机会成为僵尸进程。那么如何使父进程更方便地创建不会成为僵尸进程的子进程呢?这就要用两次fork()了。

      父进程一次fork()后产生一个子进程随后立即执行waitpid(子进程pid, NULL, 0)来等待子进程结束,然后子进程fork()后产生孙子进程随后立即exit(0)。这样子进程顺利终止(父进程仅仅给子进程收尸,并不需要子进程的返回值),然后父进程继续执行。这时的孙子进程由于失去了它的父进程(即是父进程的子进程),将被转交给Init进程托管。于是父进程与孙子进程无继承关系了,它们的父进程均为Init,Init进程在其子进程结束时会自动收尸,这样也就不会产生僵尸进程了。

  通用场景:

  一个进程要创建一个进程,两个进程同时处理任务,谁也不耽误谁。如果直接用子进程充当第二个进程的角色,那么问题是这样的:如果父进程处理时间长,子进程处理时间短,那么如果父进程不 wait() 处理的话,子进程就会成为僵尸进程,但如果父进程 wait() 子进程的话,父进程就会阻塞,所有有个方法就是让自己尽快推出,任务让子进程的子进程来处理。

 1 #include <unistd.h> 2 #include <sys/wait.h> 3 #include <stdio.h> 4 #include <stdlib.h> 5 6 int main() 7 { 8 pid_t pid; 9 if( (pid = fork()) < 0 ) 10 { 11 printf("fork error.\n"); 12 exit(-1); 13 } 14 else if(pid == 0) /* first child */ 15 { 16 if( (pid = fork()) < 0 ) 17 { 18 printf("fork error.\n"); 19 exit(-1); 20 } 21 else if(pid > 0) 22 { 23 exit(0); 24 } 25 26 /* We're the second child; our parent becomes init as soon as our real parent exits. */ 27 printf("second child, parent pid = %d\n", getppid()); 28 /* ---------------handle tasks--------------- */ 29 exit(0); 30 } 31 32 if(waitpid(pid, NULL, 0) != pid) /* wait for first child */ 33 { 34 printf("waitpid error.\n"); 35 exit(1); 36 } 37 printf("parent, first child pid = %d\n", pid); 38 /* ---------------handle tasks--------------- */ 39 40 exit(0); 41 }

 

2、通过信号机制来避免僵尸进程

  1)在父进程fork()之前安装SIGCHLD信号处理函数,并在此handler函数中调用waitpid()等待子进程结束,这样,内核才能获得子进程退出信息从而释放那个进程描述符; 

 1 #include <stdio.h> 2 #include <unistd.h> 3 #include <errno.h> 4 #include <stdlib.h> 5 #include <signal.h> 6 7 static void sig_child(int signo); 8 9 int main() 10 { 11 pid_t pid; 12 //创建捕捉子进程退出信号 13 signal(SIGCHLD,sig_child); 14 pid = fork(); 15 if (pid < 0) 16 { 17 perror("fork error:"); 18 exit(1); 19 } 20 else if (pid == 0) 21 { 22 printf("I am child process,pid id %d.I am exiting.\n",getpid()); 23 exit(0); 24 } 25 printf("I am father process.I will sleep two seconds\n"); 26 //等待子进程先退出 27 sleep(2); 28 //输出进程信息 29 system("ps -o pid,ppid,state,tty,command"); 30 printf("father process is exiting.\n"); 31 return 0; 32 } 33 34 static void sig_child(int signo) 35 { 36 pid_t pid; 37 int stat; 38 //处理僵尸进程 39 while ((pid = waitpid(-1, &stat, WNOHANG)) >0) 40 printf("child %d terminated.\n", pid); 41 } 输出结果: (^_^)root@rdenv-100#./a.out  I am father process.I will sleep two seconds I am child process,pid id 9878.I am exiting. child 9878 terminated. PID PPID S TT COMMAND 9764 9762 S pts/2 -zsh 9877 9764 S pts/2 ./a.out 9879 9877 R pts/2 ps -o pid,ppid,state,tty,command father process is exiting.

  2)设置SIGCHLD信号为SIG_IGN(即,忽略SIGHLD信号),系统将不产生僵尸进程。通过signal(SIGCHLD, SIG_IGN)通知内核对子进程的结束不关心,由内核回收。如果不想让父进程挂起,可以在父进程中加入一条语句:signal(SIGCHLD,SIG_IGN);表示父进程忽略SIGCHLD信号,该信号是子进程退出的时候向父进程发送的。常用于并发服务器的性能的一个技巧因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源。如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。  

  比如:对于服务器进程,如果父进程不等待子进程就结束,子进程将成为僵尸进程;若父进程等待子进程结束,就会影响服务器进程的并发性能。所以此时一般就将SIGCHLD信号设置为 SIG_IGN.

  注意:当我们在父进程中添加了signal(SIGCHLD,SIG_IGN)时,就不要调用waitpid函数去回收子进程了,否则会报错。man手册中有这样一段话:for waitpid() or waitid()) The process specified by pid (waitpid()) or idtype and id (waitid()) does not exist or is not a child of the calling process. (This can happen for one’s own child if the action for SIGCHLD is set to SIG_IGN. See also the Linux Notes section about threads.

  使用SIG_IGN信号引起的问题:http://blog.csdn.net/taolinke/article/details/

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/231828.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • stm32的语音识别_基于STM32的嵌入式语音识别模块设计

    stm32的语音识别_基于STM32的嵌入式语音识别模块设计引言服务机器人以服务为目的,因此人们需要一种更方便、更自然、更加人性化的方式与机器人交互,而不再满足于复杂的键盘和按钮操作。基于听觉的人机交互是该领域的一个重要发展方向。目前主流的语音识别技术是基于统计模式。然而,由于统计模型训练算法复杂,运算量大,一般由工控机、PC机或笔记本来完成,这无疑限制了它的运用。嵌入式语音交互已成为目前研究的热门课题。嵌入式语音识别系统和PC机的语音识别系统相比,虽然其…

    2022年6月26日
    33
  • 安捷伦频谱仪n9010a_安捷伦频谱仪LAN设置

    安捷伦频谱仪n9010a_安捷伦频谱仪LAN设置频谱仪操作说明按键输入所测6个频点的中心频率。(注:与步骤8对应,若所测频点为4临频输出,此处频率=第一个频点中心频率+12MHz;若所测频点为6临频输出,此处频率=第一个频点中心频率+20MHz;)20.点击“AMPTD”对应的右侧按键,液晶屏右侧出现一列选项;21.点击“Attenuation”对应的右侧按键,左右旋转按键矩阵中的旋钮键,使得频谱两边的值载噪比最大,此值即为设备的载噪比六.…

    2022年8月11日
    7
  • 大数据管理与应用专业总结笔记

    大数据管理与应用专业总结笔记大数据管理与应用专业:数据科学教育特点:不仅依赖于传统的信息管理于信息系统专业,更依赖于计算机、数学、统计等学科。大数据专业十一门涉及广泛的交叉性的学科。大数据时代的下的理念(维克托·迈尔·舍恩伯格):一是更相关性而不是因果性;二是更关注数据的纷繁复杂,而不是数据的精准;三是全部数据,而不是抽样数据。维克托·迈尔·舍恩伯格:维克托·迈尔-舍恩伯格是十余年潜心研究数据科学的技术权威,是最早洞见大数据时代发展趋势的数据科学家之一,也是最受人尊敬的权威发言人之一。**目前的形势:**目前国内新增院校还不多

    2022年6月10日
    41
  • redis 和Mysql 的一些 区别[通俗易懂]

    redis 和Mysql 的一些 区别[通俗易懂]说Redis的缓存机制实现之前,我想先回顾一下mysqlmysql存储在哪儿呢?以windows为例,mysql的表和数据,存储在data目录下frmibd后缀的文件中mysql存储在机器/服务器的硬盘中所以mysql读写数据都需要从磁盘读取。磁盘的容量,带宽的大小就影响了网站的访问速度,读取的方式,也就是sql语句,次数和效率也会影…

    2022年6月26日
    37
  • Ubuntu 16.04 下安装VMware Tools(三行命令搞定,亲测好使)

    Ubuntu 16.04 下安装VMware Tools(三行命令搞定,亲测好使)Ubuntu16.04下安装VMwareTools(三行命令搞定,亲测好使):第一行命令:sudoapt-getupgrate第二行命令:sudoapt-getinstallopen-vm-tools-desktop-y第三行命令:sudoreboot如果觉得好使,请点赞;…

    2022年5月26日
    53
  • 开源 网管 工具_智和网管平台激活成功教程版

    开源 网管 工具_智和网管平台激活成功教程版http://network.51cto.com/art/200906/129490.htm 转载于:https://blog.51cto.com/zhengj3/168618

    2022年10月5日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号