OS / Linux / SIGCHLD 信号
一、SIGCHLD 的产生条件
- 子进程终止时。
- 子进程接收到 SIGSTOP 信号停止时。
- 子进程处在停止态,接收到 SIGCONT 后唤醒时。
也就是说:子进程的运行状态发生变化就会发送 SIGCHLD 信号;这里的意思时,子进程比较依恋父母,自己发生变化就要给父母说一下。
二、借助 SIGCHLD 信号回收子进程
子进程结束运行,其父进程会收到 SIGCHLD 信号。该信号的默认处理动作是忽略,可以捕捉该信号,在捕捉函数中完成子进程状态的回收。不多说,上代码:
#include <iostream>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>void sys_err(const char *p)
{perror(p);exit(1);
}void do_sig_parent(int signal)
{int status;while (waitpid(0, &status, WNOHANG) > 0){if (WIFEXITED(status))std::cout << "子进程正常退出,状态:" << WEXITSTATUS(status) << std::endl;else if (WIFSIGNALED(status))std::cout << "子进程异常退出,状态:" << WTERMSIG(status) << std::endl;}return;
}int main()
{int i = 0;int pid = 0;for (; i < 10; ++i){if ((pid = fork()) == 0)break;else if (pid < 0)std::cout << "fork error" << std::endl;}if (i < 10)std::cout << "子进程的 ID:" << getpid() << std::endl;else{struct sigaction act, oldact;act.sa_handler = do_sig_parent;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, SIGCHLD);if (sigaction(SIGCHLD, &act, &oldact) < 0)sys_err("sigaction error");while (1){std::cout << "父进程的 ID:" << getpid() << std::endl;sleep(1);}if ((sigaction(SIGCHLD, &oldact, &act)) < 0)sys_err("sigaction error");}sleep(1);return 0;
}
结果:
子进程的 ID:15185
子进程的 ID:15188
子进程的 ID:15187
子进程的 ID:15189
子进程的 ID:15191
父进程的 ID:15184
子进程的 ID:15192
子进程的 ID:15193
子进程的 ID:15186
子进程的 ID:15190
子进程的 ID:15194
子进程正常退出,状态:0
子进程正常退出,状态:0
子进程正常退出,状态:0
父进程的 ID:15184
子进程正常退出,状态:0
子进程正常退出,状态:0
父进程的 ID:15184
子进程正常退出,状态:0
子进程正常退出,状态:0
子进程正常退出,状态:0
子进程正常退出,状态:0
子进程正常退出,状态:0
父进程的 ID:15184
父进程的 ID:15184
父进程的 ID:15184
父进程的 ID:15184
父进程的 ID:15184
父进程的 ID:15184
运行正常,父进程接收到了所有的子进程的退出消息。
现在我们来提问:可不可以将程序中,捕捉函数内部的 while 替换为 if,即将代码 while((waitpid(0, &status, WNOHANG) > 0)) 换为 if((waitpid(0, &status, WNOHANG) > 0))?为什么?
答案:不可以,修改下并运行:
子进程的 ID:15384
子进程的 ID:15385
子进程的 ID:15386
子进程的 ID:15388
父进程的 ID:15383
子进程的 ID:15390
子进程的 ID:15393
子进程的 ID:15387
子进程的 ID:15392
子进程的 ID:15389
子进程的 ID:15391
子进程正常退出,状态:0
父进程的 ID:15383
子进程正常退出,状态:0
父进程的 ID:15383
子进程正常退出,状态:0
父进程的 ID:15383
父进程的 ID:15383
父进程的 ID:15383
父进程的 ID:15383
父进程的 ID:15383
父进程的 ID:15383
可以发现,有 7 个子进程的退出状态父进程没有捕获到,原因是 if 只执行一次回收(因为到了那儿说明父进程收到信号了,也就是说一定有子进程死掉了。)但是若是某一个时刻有多个子进程同时死了,那么依据信号不进行排队的原理,就只有其中一个信号被处理,其他的被忽略。但是 while 就不一样了,就算同时来多个信号,但是 while 时循环执行,虽然信号处理先后顺序不一样,但是每个信号都会被处理啊(非阻塞的 waitpid 函数)。
所以啊,当有多个子进程时,回收的时候用循环,不要用 if。
参考:https://blog.csdn.net/weixin_30752699/article/details/97366496
(SAW:Game Over!)
OS / Linux / SIGCHLD 信号相关推荐
- linux SIGCHLD信号
SIGCHLD的产生条件 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 借助SIGCHLD信号回收子进程 子进程结束运行,其父进程会收到SIGCH ...
- Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号
首先区分一下Linux信号跟进程间通信中的信号量,它们的关系就犹如老婆跟老婆饼一样,没有一毛钱的关系. 信号的概念 信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断.比如:红绿灯是一种信号 ...
- linux下的僵尸进程处理SIGCHLD信号【转】
转自:http://www.cnblogs.com/wuchanming/p/4020463.html 什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打 ...
- 【Linux】SIGCHLD信号
文章目录 SIGCHLD信号 SIGCHLD信号 回忆: 为了避免出现僵尸进程,父进程需要使用wait或waitpid函数等待子进程结束,父进程可以阻塞等待子进程结束,也可以非阻塞地查询的是否有子进程 ...
- [ Linux ] 可重入函数,volatile 关键字,SIGCHLD信号
目录 1.可重入函数 2.volatile 2.1从信号角度理解volatile的作用 2.2volatile的作用 3.SIGCHLD信号 3.1SIGCHLD信号的验证 1.可重入函数 在数据结构 ...
- Day53 Linux setitimer函数 信号集操作函数 信号捕捉 SIGCHLD信号
目录 setitimer函数 信号集操作函数 1.信号集设定 2.igprocmask函数 3.sigpending函数 信号捕捉 1.signal函数 2.sigaction函数 SIGCHLD信号 ...
- Linux解决僵尸进程的几种方式,SIGCHLD信号设置SIG_IGN处理方式等
目录 僵尸进程 解决方式 父进程阻塞调用wait() 父进程非阻塞调用waitpid() SIGCHLD信号 SIG_IGN信号 僵尸进程 我们知道linux下进程有种状态叫做僵尸状态; 原因是父进程 ...
- 【Linux信号专题】五、SIGCHLD信号详解
欢迎关注博主 Mindtechnist 或加入[Linux C/C++/Python社区]一起探讨和分享Linux C/C++/Python/Shell编程.机器人技术.机器学习.机器视觉.嵌入式AI ...
- 【Linux】SIGCHLD信号解决僵尸进程问题
1. 基本信息 SIGCHLD信号产生的条件: 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 以上三种条件都会给父进程发送SIGCHLD信号,父进 ...
最新文章
- Linux从mysql中读取数据_linux shell中读写操作mysql数据库
- ueditor初始化
- ubuntu 新建一个root用户
- 2011年使用率增长最快的十大Web技术
- 从阿里云七代云服务器,谈云计算四大趋势
- 一分钟学会python编程_用Python教你一分钟检验出来!不用群发_编程语言_Python课程_Python教程_课课家...
- Flutter CustomScrollView实现的一个经典滑动折叠头部图片的效果
- 【kafka】kafka offset 的存储 (存储zookeeper 与 存储 kafka)
- VS2015解决方案资源管理器空白,不显示内容
- “社区之星”(社区核心贡献者)成长故事征集
- 电子设计(2)三极管稳压电路仿真分析
- CSDN博客排版格式入门
- 常见电路面试题20道
- 自下而上构建知识图谱全过程
- 基于 EG6831 的无感 BLDC 控制方案
- 自建app服务器架构特点
- RAD Studio XE (DelphiXE)官网下载地址与注册
- qemu图形界面linux,QEMU 简单几步搭建一个虚拟的ARM开发板
- 码农的2019又开始了,抓不住重点的我很悲催
- python opencv 校准鱼眼相机
热门文章
- Android IOS WebRTC 音视频开发总结(七九)-- WebRTC选择H.264的四大理由
- Tomcat7和mysql连接池dbcp方式的配置方法和测试
- [LeetCode]题解(python):025-Reverse Nodes in k-Group
- 利用WireShark分析由Ping产生的Internet 控制报文协议(ICMP)
- 高清精美壁纸:2013年9月桌面日历壁纸免费下载
- 迁移和升级windows 2003 R2到windows 2008 SP2
- HTML用a标签出现404,404.html
- 2020 操作系统第三次习题
- hadoop学习笔记:运行wordcount对文件字符串进行统计案例
- “ShardingCore”是如何针对分表下的分页进行优化的