SIGCHLD的产生条件

子进程状态发生变化就会产生SIGCHLD信号

1、子进程终止时

2、子进程接收到SIGSTOP信号停止时

3、子进程处在停止态,接受到SIGCONT后唤醒时

借助 SIGCHLD 信号回收子进程 (重要)

借助信号回收子进程https://www.bilibili.com/video/BV1KE411q7ee?p=143&spm_id_from=pageDriver&vd_source=d239c7cf48aa4f74eccfa736c3122e65

子进程执行结束之后,父进程如果不对其进行回收,子进程就会变为僵尸进程。
父进程可以通过调用wait()函数和waitpid()函数去回收子进程。

目前有两种方法来进行回收僵尸进程

1.wait阻塞方式        2.waitpid的轮询模式。

这两种方式都会导致父进程无法干别的事。

子进程结束运行,其父进程会收到SIGCHLD信号。该信号的默认处理动作是忽略。可以捕捉该信号,在捕捉函数中完成子进程状态的回收。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>void cat_sigchild(int sig) //有子进程终止,发送SIGCHLD信号时,该函数会被内核回调
{int status;pid_t pid;//if((wpid = wait(NULL)) != -1)  //常规信号不支持排队,不能这么写while((pid =  waitpid(0,&status,WNOHANG)) > 0) //循环回收,防止僵尸进程出现{if(WIFEXITED(status))  //获取子进程退出状态,并打印{printf("child exit with %d\n",WEXITSTATUS(status));}else if(WIFSIGNALED(status)){printf("child kill by sig %d\n",WTERMSIG(status));}}
}int main(int argc,char *argv[])
{pid_t pid;//阻塞SIGCHLD信号sigset_t newset,oldset;sigemptyset(&newset);        sigaddset(&newset,SIGCHLD);sigprocmask(SIG_BLOCK,&newset,&oldset);//如果在信号捕捉函数设置之前,子进程先结束,那么如果提前不阻塞SIGCHLD信号的话,//就会导致先结束的子进程无法回收,所以在设置信号捕捉函数之前应该先阻塞SIGCHLD信号。int i;for(i=0;i<10;i++){pid = fork(); //创建多个子进程if(pid == 0){break;}else if(pid <0){perror("fork:");exit(1);}}if(pid == 0){printf("i am %d child pid is %d\n",i+1,getpid());return i+1;}else if(pid >0){int n = 10000000;//sleep(4);//阻塞SIGCHLD信号  为什么可以在这?/*sigset_t newset,oldset;sigemptyset(&newset);        sigaddset(&newset,SIGCHLD);sigprocmask(SIG_BLOCK,&newset,&oldset);*/while(n --)  //模拟程序执行,让子进程先结束。{}//父进程中注册捕获信号函数struct sigaction act,oldact;act.sa_handler = cat_sigchild;act.sa_flags = 0;sigemptyset(&act.sa_mask);   //信号捕捉函数执行期间,sa_mask会被替换掉sigaction(SIGCHLD,&act,NULL);//解除阻塞sigprocmask(SIG_SETMASK,&oldset,NULL); //如果不解除阻塞,回调函数没有执行机会while(1){printf("parent id %d\n",getpid());sleep(1);}}return 0;
}

注意点:
这里需要注意的是:我们在设置SIGCHLD信号的信号捕捉函数之前为了程序的严谨性,要先使用系统函数sigprocmask()去阻塞SIGCHLD信号,在设置完SIGCHLD信号的信号捕捉函数之后再解除阻塞。
原因:
如果我们的子进程先于父进程执行,假如在父进程设置完SIGCHLD的信号捕捉函数之前所有子进程都执行结束了,那么父进程就不会再收到子进程发送的SIGCHLD信号,信号捕捉函数就不会执行,进而回收子进程的系统函数waitpid()就不会被调用,那么就会造成所有的子进程变为僵尸进程。

解决办法:
        1:设置信号阻塞,在父进程设置完SIGCHLD信号的信号捕捉函数之前阻塞SIGCHLD信号。这样即使所有的子进程都结束了,由于信号处于阻塞状态,当我们设置完SIGCHLD信号的捕捉函数之后,解除阻塞,就可以正常捕获到子进程发送的SIGCHLD信号,就可以进入捕捉函数调用waitpid去回收 死去的子进程 的资源。
        注意: 这里想要回收所有子进程调用waitpid必须使用while循环结构,不能使用if结构。因为在执行SIGCHLD信号捕捉函数期间,如果两个或多个子进程同时结束,那么SIGCHLD信号只记录一次,此时如果使用if结构就会导致同时结束的子进程只回收一个。

2:我们可以人为的使用kill -17 (父进程号) 命令给父进程发送SIGCHLD信号,就会触发信号捕捉函数,在捕捉函数内部利用
        while((pid = waitpid(0,&status,WNOHANG)) > 0) 结构去回收所有死掉的子进程。
注意:在父进程之前死掉的子进程发送的SIGCHLD信号默认动作为忽略,所以可以将之前先于父进程死掉的子进程回收靠的并不是之前子进程的SIGCHLD信号,而是靠的后来收到的SIGCHLD信号,和waitpid函数.

在这种人为发送信号回收的情况下:
SIGCHLD信号捕捉函数只调用执行一次,waitpid函数执行多次,才可以将之前死掉的所有子进程回收。

SIGCHLD信号注意问题

  1. 子进程继承父进程的信号屏蔽字和信号处理动作,但子进程没有继承未决信号集spending。
  2. 注意注册信号捕捉函数的位置。
  3. 应该在fork之前,阻塞SIGCHLD信号。注册完捕捉函数后解除阻塞。

SIGCHLD信号(重点)相关推荐

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

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

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

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

  3. OS / Linux / SIGCHLD 信号

    一.SIGCHLD 的产生条件 子进程终止时. 子进程接收到 SIGSTOP 信号停止时. 子进程处在停止态,接收到 SIGCONT 后唤醒时. 也就是说:子进程的运行状态发生变化就会发送 SIGCH ...

  4. Linux--信号signal、父子进程、SIGCHLD信号相关命令

    目录 1.概念: 2.信号的存储位置: 3.常见的信号的值以及对应的功能说明: 4.信号的值在系统源码中的定义: 5.响应方式: 6.改变信号的相应方式: (1)设置信号的响应方式: (2)默认:SI ...

  5. linux的SIGCHLD信号

    SIGCHLD信号 SIGCHLD的产生条件 子进程终止时 子进程接收到SIGSTOP信号停止时 子进程处在停止态,接受到SIGCONT后唤醒时 借助SIGCHLD信号回收子进程 #include & ...

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

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

  7. Linux信号:SIGCHLD信号和僵尸进程

    1. SIGCHLD信号产生条件: (1)子进程终止: (2)子进程收到SIGSTOP信号被暂停: (3)子进程处于暂停状态,收到SIGCONT信号被唤醒. 2. 捕捉SIGCHLD,避免僵尸进程: ...

  8. 【Linux】SIGCHLD信号

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

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

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

最新文章

  1. 实用的项目管理系统,才能让协同工作更顺畅
  2. 跟我学Spring Cloud(Finchley版)-10-Feign深入
  3. 《Unity 3D 游戏开发技术详解与典型案例》——1.3节第一个Unity 3D程序
  4. 【Pytorch神经网络基础理论篇】 04 线性代数
  5. Leetcode算法题(C语言)13--反转字符串
  6. LightOJ1234 Harmonic Number
  7. jquery[学习心得]ajax的注意点
  8. IDEA 编译构建等工程配置
  9. 微信AI开放接口介绍
  10. git提交本地代码到新分支
  11. gatedata graph digitier 基本使用
  12. JVM内存管理--GC算法精解(五分钟教你终极算法---分代搜集算法)
  13. Halcon教程一 :软件入门
  14. RHEL5.4配置自动挂载器
  15. cam_lidar_calib激光雷达和相机联合标定
  16. [转帖]*野外生活手册~
  17. 不良事件总结怎么写_年度不良事件总结
  18. 反向延长线段什么意思_反向延长线是什么意思
  19. python输入一个正整数、计算其各个位的数字之和_C语言程序设计:编写程序,输入一个正整数,统计该整数的位数并计算其各个数位上的数字之和。...
  20. 关于activity的生命周期1

热门文章

  1. 如何临时修改ip地址,永久修改ip地址
  2. (二)弹性布局Flex
  3. Ubuntu16.0.4 安装rebar3指南
  4. python 证书-Python 发送带自签名证书的 https 请求
  5. Web3赋能创作者经济:NFT,DAO和永续收入
  6. 做好每周工作总结很重要
  7. 财务报告及会计基础知识
  8. pandas筛选数据_2_条件筛选
  9. 关于电子科技大学宿舍安装热水的调查
  10. MySQL中delete结合exist删除数据