回收子进程——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的调试相对比较方便,因为可以通过 ...
随机推荐
- STM32F103单片机学习—— 通用定时器
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/fengshuiyue/article/details/79150724 本篇重点记录的是STM32F ...
- note2
- 【leetcode】636. Exclusive Time of Functions
题目如下: 解题思路:本题和括号匹配问题有点像,用栈比较适合.一个元素入栈前,如果自己的状态是“start”,则直接入栈:如果是end则判断和栈顶的元素是否id相同并且状态是“start”,如果满足这 ...
- Linux系统重要文件
Linux系统重要文件介绍与配置 一网卡配置文件 (一)网卡配置文件参数介绍 文件路径信息:/ec/sysconfig/network-scripts/ifcfg-eth0 文件作用说明:配置网卡地址 ...
- Java反射学习-1 - 反射获取类的属性,方法,构造器
新建一个Person类 package cn.tx.reflect; /** * 注解初步了解 * @author Administrator * */ public class Person { p ...
- CNN笔记:通俗理解卷积神经网络
CNN笔记:通俗理解卷积神经网络 2016年07月02日 22:14:50 v_JULY_v 阅读数 250368更多 分类专栏: 30.Machine L & Deep Learning 机 ...
- Java的Object几个重写的方法
1:toString(); 只是简单的列出对象的状态(也就是重要的实例变量的当前值). package jicheng;public class Animal { public static void ...
- LOJ 2997 「THUSCH 2017」巧克力——思路+随机化+斯坦纳树
题目:https://loj.ac/problem/2977 想到斯坦纳树.但以为只能做 “包含一些点” 而不是 “包含一些颜色” .而且不太会处理中位数. 其实 “包含一些颜色” 用斯坦纳树做也和普 ...
- Gym10198-Mediocre String Problem-2018南京ICPC现场赛
目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门 Portal 原题目描述在最下面. Solu ...
- js中forEach,for in,for of循环的用法
from:https://www.cnblogs.com/amujoe/p/8875053.html 一.一般的遍历数组的方法: var array = [1,2,3,4,5,6,7]; for (v ...