回收子进程——wait/waitpid 与 信号机制
孤儿/僵尸进程——回收子进程
参考博客: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 与 信号机制的更多相关文章
- 在Linux中简单实现回收子进程
学习到wait函数了,这个函数的作用是用来回收进程.一般来说,正常退出的进程是不需要我们来专门回收的.但是进程有这两种:孤儿进程和僵尸进程. 孤儿进程: 通俗点说就是父进程先于子进程死亡.此时子进程就 ...
- Linux-父进程wait回收子进程
1.wait工作原理 (1).子进程结束时,系统向其父进程发送SIGCHILD信号 (2).父进程调用wait函数后阻塞 (3).父进程被SIGCHILD信号唤醒然后去回收僵尸子进程 (4).父子进程 ...
- linux信号机制与python信号量
1.信号本质 软中断信号(signal,又简称为信号)用来通知进程发生了异步事件.在软件层次上是对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是一样的.信号是进程间 ...
- Linux信号机制
Linux信号(signal) 机制分析 [摘要]本文分析了Linux内核对于信号的实现机制和应用层的相关处理.首先介绍了软中断信号的本质及信号的两种不同分类方法尤其是不可靠信号的原理.接着分析了内核 ...
- linux下 signal信号机制的透彻分析与各种实例讲解
转自:http://blog.sina.com.cn/s/blog_636a55070101vs2d.html 转自:http://blog.csdn.net/tiany524/article/det ...
- python使用信号机制实例:
python使用信号机制实例: 程序会一直等待,直到其他程序发送CTRL-C信号给本进程.需要其他程序配合测试. 或者打开新的终端使用kill -sig PID 向一个进程发送信号,来测试. from ...
- Inside Flask - signal 信号机制
Inside Flask - signal 信号机制 singal 在平常的 flask web 开发过程中较少接触到,但对于使用 flask 进行框架级别的开发时,则必须了解相关的工作机制.flas ...
- linux信号机制 - 用户堆栈和内核堆栈的变化【转】
转自:http://itindex.net/detail/16418-linux-%E4%BF%A1%E5%8F%B7-%E5%A0%86%E6%A0%88 此文只简单分析发送信号给用户程序后,用户堆 ...
- 利用linux信号机制调试段错误(Segment fault)
在实际开发过程中,大家可能会遇到段错误的问题,虽然是个老问题,但是其带来的隐患是极大的,只要出现一次,程序立即崩溃中止.如果程序运行在PC中,segment fault的调试相对比较方便,因为可以通过 ...
随机推荐
- windows平台搭建Mongo数据库复制集(类似集群)(二)
通过rs.status()命令我们可以查询到各个节点运行正常. 一.数据同步测试 在28011.28012端口上进行插入: 因为SECONDARY是不允许读写的, 在写多读少的应用中,使用Replic ...
- 动态规划之数字三角形(POJ1163)
在下面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大.路径上的每一步都只能往左下或 右下走.只需要求出这个最大和即可,不必给出具体路径. 既然求目标问题是根据查表得来的,自然 ...
- 使用字符流(Writer、Reader)完成对文件的读写操作
字符流 字符输出流:Writer,对文件的操作使用子类FileWriter 字符输入流:Reader,对文件的操作使用子类FileReader 每次操作的是一个字符 文件字符操作流会自带缓存,默认大小 ...
- C# 批量修改考勤设备时间
自己工作中用到的小程序,每次远行后批量改一次 如下: 其中的zkemkeeper是中控的相关组件,因是系统组件,须要先注册相关文件后才有效 using System; using System.Col ...
- Linux中的bin文件夹
~/bin适合放个人用户的 script /usr/local/bin存放系统中所有用户都可以使用的 script /usr/local/sbin存放管理员的 script /usr/local/目录 ...
- bootstrap响应式布局原理
百分比布局+媒体查询 首先通过媒体查询确认container的宽度,每个col-xx-xx都是通过百分比定义的,屏幕尺寸变化了,container就变化了,col自然就变了 Bootstrap的官方解 ...
- Linux系统重要文件
Linux系统重要文件介绍与配置 一网卡配置文件 (一)网卡配置文件参数介绍 文件路径信息:/ec/sysconfig/network-scripts/ifcfg-eth0 文件作用说明:配置网卡地址 ...
- shell脚本学习 (8) fmt 格式化段落
1 获取系统中的字典文件 -n隐藏查找过程 -e 匹配多次,只打印带p的行(不能写成-e -n) ,100p /usr/share/dict/words 会显示1-100行的字母 2 fmt 按默认 ...
- 处理警告:编码 GBK 的不可映射字符
怎么处理警告:编码 GBK 的不可映射字符:javac -encoding UTF-8 XX.java使用-encoding参数指明编码方式: 或者 用记事本打开文件,然后另存为,选择ANSI编码,覆 ...
- Microsoft Office Excel
解除合并,并复制原始值到每一个解除合并后的单元格 对齐方式 -> 合并后居中 -> 取消单元格合并 编辑 -> 查找和选择 -> 定位条件 -> 空值 输入=然后按↑选择 ...