孤儿/僵尸进程——回收子进程

参考博客:https://blog.csdn.net/qq_35396127/article/details/78725915

    :https://www.cnblogs.com/Anker/p/3271773.html

  在Linux下,子进程可由父进程创建,子进程也可以创建新的进程。但是父进程无法预测子进程的运行状态,不知道子进程何时会结束。由此会产生孤儿进程与僵尸进程。所以当一个进程结束后,它的父进程需要调用wait(),waitpid()系统调用获取子进程终止状态,回收子进程。

  什么是孤儿进程与僵尸进程?

  孤儿进程:

  父进程先于子进程结束,则子进程失去父进程,子进程就会被init 进程收养,子进程就成为孤儿进程。

 #include <stdio.h>
#include <stdlib.h>
#include <unistd.h> int main(void)
{
pid_t pid;
int i=;
//创建一个子进程
pid = fork(); if(pid == -)
{
perror("fork");
exit(); //1:异常退出 0:正常退出
}
else if(pid>)
{
printf("I am parent, my pid=%d\n",getpid());
sleep(); //父进程运行4秒后结束
printf("---------parent going to die-----------\n"); }
else
{
while(i<)
{
//待父进程结束后会被init收养
printf("I am child, pid = %d, parentpid = %d\n",getpid(),getppid());
sleep();
i++;
}
}
return ;
}

结果:

有的Ubuntu版本,会设置user init 进程专门处理孤儿进程

僵尸进程:

  子进程终止,父进程未回收子进程的资源PCB,使其变成僵尸进程。

测试程序:

 #include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h> int main(){ pid_t pid;
pid = fork();
if(pid < )
{
perror("fork error:");
exit();
}
else if (pid == )
{
printf("I am child, I am exiting.\n");
exit();
} printf("I am parent,I will sleep 2s\n");
//等待子进程先退出
sleep();
//输出进程信息
system("ps -o pid,ppid,state,tty,command");
printf("father process exiting\n"); return ;
} 源自:https://www.cnblogs.com/Anker/p/3271773.html

结果:

  孤儿进程与僵尸进程的危害

  在Linux中,每个进程退出时,内核会释放该进程所有资源,包括打开的文件,占用的内存等,但仍为之保留一定信息,包括:进程ID,退出状态,运行时间等。直到父进程通过wait/waitpid来取时,才会释放。因此,只要进程一直调用wait与waitpid,进程占用的资源就不会释放,进程号也不会释放,由于系统能使用的进程号是有限的,就可能因为大量僵尸进程占用进程号而不能产生新进程。当系统中产生大量僵尸进程时,应该把产生僵尸进程的父进程给杀死掉。可以通过kill发送SIGTERM或者SIGKILL信号,之后僵尸进程会因为没了父进程变成孤儿,被init收养再释放。

  对于孤儿进程,会被init进程收养,而且init进程会循环地wait()它收养的子进程。所以孤儿进程并无危害。

  通过信号机制解决僵尸进程

  子进程退出时会向父进程发送SIGCHLD信号,父进程调用信号处理函数,进而调用wait处理僵尸进程。测试程序:

 #include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h> static void handlefunc(int sig)
{
pid_t pid;
int stat; //处理僵尸进程
//waitpid(-1:回收任一子进程,子进程结束状态,不阻塞父进程)
//waitpid成功返回子进程pid
while((pid = waitpid(-, &stat, WNOHANG))>)
printf("child %d terminated. \n",pid);
} int main()
{
pid_t pid;
//创建signal,捕捉子进程退出信号
signal(SIGCHLD,handlefunc);
pid = fork();
if(pid<)
{
perror("fork error:");
exit();
}
else if(pid == )
{
printf("I am chid, pid=%d. I exiting\n",getpid());
exit();
}
printf("I am parent. I sleep 3S\n");
//等待子进程退出
sleep();
//输出进程信息
system("ps -o pid,ppid,state,tty,command");
printf("parent exiting"); return ; }

结果:僵尸进程消失

signal(SIGCLD,SIG_IGN);

因为并发服务器常常fork很多子进程,子进程终结之后需要服务器进程去wait清理资源。如果将此信号的处理方式设为忽略,可让内核把僵尸子进程转交给init进程去处理,省去了大量僵尸进程占用系统资源。

详见:https://blog.csdn.net/u012317833/article/details/39253793

回收子进程——wait/waitpid 与 信号机制的更多相关文章

  1. 在Linux中简单实现回收子进程

    学习到wait函数了,这个函数的作用是用来回收进程.一般来说,正常退出的进程是不需要我们来专门回收的.但是进程有这两种:孤儿进程和僵尸进程. 孤儿进程: 通俗点说就是父进程先于子进程死亡.此时子进程就 ...

  2. Linux-父进程wait回收子进程

    1.wait工作原理 (1).子进程结束时,系统向其父进程发送SIGCHILD信号 (2).父进程调用wait函数后阻塞 (3).父进程被SIGCHILD信号唤醒然后去回收僵尸子进程 (4).父子进程 ...

  3. linux信号机制与python信号量

    1.信号本质 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间 ...

  4. Linux信号机制

    Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...

  5. linux下 signal信号机制的透彻分析与各种实例讲解

    转自:http://blog.sina.com.cn/s/blog_636a55070101vs2d.html 转自:http://blog.csdn.net/tiany524/article/det ...

  6. python使用信号机制实例:

    python使用信号机制实例: 程序会一直等待,直到其他程序发送CTRL-C信号给本进程.需要其他程序配合测试. 或者打开新的终端使用kill -sig PID 向一个进程发送信号,来测试. from ...

  7. Inside Flask - signal 信号机制

    Inside Flask - signal 信号机制 singal 在平常的 flask web 开发过程中较少接触到,但对于使用 flask 进行框架级别的开发时,则必须了解相关的工作机制.flas ...

  8. linux信号机制 - 用户堆栈和内核堆栈的变化【转】

    转自:http://itindex.net/detail/16418-linux-%E4%BF%A1%E5%8F%B7-%E5%A0%86%E6%A0%88 此文只简单分析发送信号给用户程序后,用户堆 ...

  9. 利用linux信号机制调试段错误(Segment fault)

    在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...

随机推荐

  1. create-react-app按需引入antd-mobile

    1.引入 react-app-rewired 并修改 package.json 里的启动配置: npm i react-app-rewired@2.0.2-next.0 // 需要安装低版本 否则np ...

  2. Python 石头 剪刀 布

    di = {1: '石头', 2: '剪刀', 3: '布'} def win(x, y): if len({x[0], y[0]}) == 1: print('平局.') else: if {x[0 ...

  3. 【leetcode】1020. Partition Array Into Three Parts With Equal Sum

    题目如下: Given an array A of integers, return true if and only if we can partition the array into three ...

  4. springMVC的controller更改了,如何不重启,而自动刷新的解决办法(亲测,一招解决)

    Tomcat  con/ service.xml  配置如下一行代码: <Context reloadable="true"/> </Host> 然后以de ...

  5. python的main函数

    代码示例:test.py import sys if __name__ == '__main__' size = len(sys.argv) p1 = sys.argv[] p2 = sys.argv ...

  6. webpackES6语法转ES5语法

    安装babel-loader: npm install --save-dev babel-loader@7 babel-core babel-preset-es2015 webpack.config. ...

  7. JDBC调用oracle 存储过程

    1.创建一个oracle存储过程 p_empInfo2 并执行,使这段sql代码能编译存储到oracle数据库中. --输入员工号查询某个员工(7839)信息,将薪水作为返回值输出,给调用的程序使用 ...

  8. IGServer for Java

    Eclipse和JavaEE: DCServer是哪个? 查看服务器文件夹: Env_Var变量没有定义:JRE_HOME.JDK_HOME 这是Tomcat报错的提示,但是既然JAVA_HOME都有 ...

  9. 2018-2019-2 20175126谢文航 实验三《敏捷开发与XP实践》实验报告

    一.实验报告封面 课程:Java程序设计 班级:1751 班 姓名:谢文航 学号:20175126 指导教师:娄嘉鹏 实验日期:2019年5月2日 实验时间:--- 实验序号:实验三 实验名称:敏捷开 ...

  10. Php安装时出现的问题处理

    问题从这里开始,我们一步一步说明: cd /usr/local/src/ tar zxvf php-5.5.6.tar.gz cd php-5.5.6 ./configure \ //执行当前目录下软 ...