一、SIGCHLD 的产生条件

  1. 子进程终止时。
  2. 子进程接收到 SIGSTOP 信号停止时。
  3. 子进程处在停止态,接收到 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 信号相关推荐

  1. linux SIGCHLD信号

    SIGCHLD的产生条件 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 借助SIGCHLD信号回收子进程 子进程结束运行,其父进程会收到SIGCH ...

  2. Linux进程信号(产生、保存、处理)/可重入函数概念/volatile理解/SIGCHLD信号

    首先区分一下Linux信号跟进程间通信中的信号量,它们的关系就犹如老婆跟老婆饼一样,没有一毛钱的关系. 信号的概念 信号的概念:信号是进程之间事件异步通知的一种方式,属于软中断.比如:红绿灯是一种信号 ...

  3. linux下的僵尸进程处理SIGCHLD信号【转】

    转自:http://www.cnblogs.com/wuchanming/p/4020463.html 什么是僵尸进程? 首先内核会释放终止进程(调用了exit系统调用)所使用的所有存储区,关闭所有打 ...

  4. 【Linux】SIGCHLD信号

    文章目录 SIGCHLD信号 SIGCHLD信号 回忆: 为了避免出现僵尸进程,父进程需要使用wait或waitpid函数等待子进程结束,父进程可以阻塞等待子进程结束,也可以非阻塞地查询的是否有子进程 ...

  5. [ Linux ] 可重入函数,volatile 关键字,SIGCHLD信号

    目录 1.可重入函数 2.volatile 2.1从信号角度理解volatile的作用 2.2volatile的作用 3.SIGCHLD信号 3.1SIGCHLD信号的验证 1.可重入函数 在数据结构 ...

  6. Day53 Linux setitimer函数 信号集操作函数 信号捕捉 SIGCHLD信号

    目录 setitimer函数 信号集操作函数 1.信号集设定 2.igprocmask函数 3.sigpending函数 信号捕捉 1.signal函数 2.sigaction函数 SIGCHLD信号 ...

  7. Linux解决僵尸进程的几种方式,SIGCHLD信号设置SIG_IGN处理方式等

    目录 僵尸进程 解决方式 父进程阻塞调用wait() 父进程非阻塞调用waitpid() SIGCHLD信号 SIG_IGN信号 僵尸进程 我们知道linux下进程有种状态叫做僵尸状态; 原因是父进程 ...

  8. 【Linux信号专题】五、SIGCHLD信号详解

    欢迎关注博主 Mindtechnist 或加入[Linux C/C++/Python社区]一起探讨和分享Linux C/C++/Python/Shell编程.机器人技术.机器学习.机器视觉.嵌入式AI ...

  9. 【Linux】SIGCHLD信号解决僵尸进程问题

    1. 基本信息 SIGCHLD信号产生的条件: 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 以上三种条件都会给父进程发送SIGCHLD信号,父进 ...

最新文章

  1. Linux从mysql中读取数据_linux shell中读写操作mysql数据库
  2. ueditor初始化
  3. ubuntu 新建一个root用户
  4. 2011年使用率增长最快的十大Web技术
  5. 从阿里云七代云服务器,谈云计算四大趋势
  6. 一分钟学会python编程_用Python教你一分钟检验出来!不用群发_编程语言_Python课程_Python教程_课课家...
  7. Flutter CustomScrollView实现的一个经典滑动折叠头部图片的效果
  8. 【kafka】kafka offset 的存储 (存储zookeeper 与 存储 kafka)
  9. VS2015解决方案资源管理器空白,不显示内容
  10. “社区之星”(社区核心贡献者)成长故事征集
  11. 电子设计(2)三极管稳压电路仿真分析
  12. CSDN博客排版格式入门
  13. 常见电路面试题20道
  14. 自下而上构建知识图谱全过程
  15. 基于 EG6831 的无感 BLDC 控制方案
  16. 自建app服务器架构特点
  17. RAD Studio XE (DelphiXE)官网下载地址与注册
  18. qemu图形界面linux,QEMU 简单几步搭建一个虚拟的ARM开发板
  19. 码农的2019又开始了,抓不住重点的我很悲催
  20. python opencv 校准鱼眼相机

热门文章

  1. Android IOS WebRTC 音视频开发总结(七九)-- WebRTC选择H.264的四大理由
  2. Tomcat7和mysql连接池dbcp方式的配置方法和测试
  3. [LeetCode]题解(python):025-Reverse Nodes in k-Group
  4. 利用WireShark分析由Ping产生的Internet 控制报文协议(ICMP)
  5. 高清精美壁纸:2013年9月桌面日历壁纸免费下载
  6. 迁移和升级windows 2003 R2到windows 2008 SP2
  7. HTML用a标签出现404,404.html
  8. 2020 操作系统第三次习题
  9. hadoop学习笔记:运行wordcount对文件字符串进行统计案例
  10. “ShardingCore”是如何针对分表下的分页进行优化的