Linux中sigaction函数和SIGCHLD信号的使用
sigaction函数:
函数说明:注册一个信号处理函数
函数原型:int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
函数参数:
- signum:捕捉的信号
- act:传入参数,新的处理方式
- oldact:传出参数,旧的处理方式
The sigaction structure is defined as something like:struct sigaction {void (*sa_handler)(int);//信号处理函数void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;//信号处理函数执行期间需要阻塞的信号,信号处理函数结束后,就不阻塞了int sa_flags;//通常为0,表示默认标识void (*sa_restorer)(void);};
测试:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <signal.h>
#include <sys/time.h>
void handler(int signo)
{printf("signo==[%d]\n",signo);sleep(5);
}
int main()
{//int sigaction(int signum, const struct sigaction *act,// struct sigaction *oldact);struct sigaction act;act.sa_handler=handler;sigemptyset(&act.sa_mask);把set信号集全部置0,不阻塞任何信号act.sa_flags=0;sigaction(SIGINT,&act,NULL);while(1){sleep(1);}return 0;
}
结果:

由结果我们可以知道在XXX信号处理函数执行期间,当XXX信号产生多次,该信号进入未决信号集中(被阻塞),在信号处理函数执行结束后,只会执行一次(信号不支持排队)。
若在sa_mask中阻塞了YYY信号,那么在XXX信号处理函数执行时,产生的YYY信号也会进入未决信号集中(被阻塞),等到XXX信号处理函数结束后执行一次。
SIGCHLD信号:
产生SIGCHLD信号的条件:
- 子进程结束的时候
- 子进程收到SIGSTOP信号
- 当子进程停止时,收到SIGCONT信号
SIGCHLLD信号的作用:
子进程退出后,内核会给它的父进程发送SIGCHLD信号,父进程收到这个信号后可以使用wait/waitpid函数对子进程进行回收。
父进程创建两个子进程,然后让父进程捕获SIGCHLD信号完成对子进程的回收
注意点:
有可能还未完成注册信号处理函数,两个子进程已经都退出了
解决方法:可以在fork之前先将SIGCHLD阻塞,当完成信号处理函数的注册后解除阻塞
当SIGCHLD信号函数处理期间,SIGCHLD信号若再次产生是被阻塞的,而且产生多次,最后只会被处理一次,这样就会产生僵尸进程
解决方法:可以在信号处理函数里面使用while(1)循环回收,这样就有可能出现捕获一次SIGCHLD信号但是回收了多个子进程的情况,从而避免产生僵尸进程
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include<signal.h>
void handler(int signo)//信号处理函数
{//pid_t waitpid(pid_t pid, int *wstatus, int options);pid_t wpid;while(1)//一直死循环,防止信号处理函数执行的时候,有多个子进程终止(只会接收一次SIGCHLD信号),产生僵尸进程{wpid=waitpid(-1,NULL,WNOHANG);//设为非阻塞,因为子进程收到SIGSTOP,SIGCONT信号,也会发出SIGCHLD信号,这样一来并没有子进程终止,就会一直阻塞if(wpid>0){printf("[%d]child is quit\n",wpid);}else if(wpid==0)//还有子进程运行,break,等下一个SIGCHLD信号{break;}else if(wpid==-1)//没有子进程,已经全部回收,break{printf("no child is living\n");break;}}
}
int main()
{
//先把SIGCHLD信号阻塞,防止还没有注册信号处理函数时,就已经有SIGCHLD信号产生,被忽略sigset_t set;sigemptyset(&set);sigaddset(&set,SIGCHLD);
// int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);sigprocmask(SIG_BLOCK,&set,NULL);int i=0;for(;i<2;i++)//循环产生两个兄弟子进程{pid_t pid=fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){printf("father:pid=[%d]\n",getpid());}else if(pid==0){break;}}if(i==0){printf("[%d]child:pid=[%d],fpid=[%d]\n",i,getpid(),getppid());}else if(i==1){printf("[%d]child:pid=[%d],fpid=[%d]\n",i,getpid(),getppid());}else if(i==2){struct sigaction act;act.sa_handler=handler;sigemptyset(&act.sa_mask);act.sa_flags=0;sigaction(SIGCHLD,&act,NULL);//注册信号处理函数sigprocmask(SIG_UNBLOCK,&set,NULL);//把SIGCHLD信号设置为非阻塞while(1){sleep(1);}}return 0;
}
结果:
使用信号传递让父子进程来回计数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<unistd.h>
#include<signal.h>
//定义成全局变量,不然回调函数无法辨认
int num=0;//从0开始计数
int flag=0;//开关变量
void func1(int signo)//父进程的信号处理函数
{printf("f:[%d]\n",num);num+=2;flag=0;sleep(1);
}
void func2(int signo)//子进程的信号处理函数
{printf("c:[%d]\n",num);num+=2;flag=0;sleep(1);
}
int main()
{pid_t pid=fork();if(pid<0){perror("fork error");return -1;}else if(pid>0){signal(SIGUSR1,func1);//注册信号处理函数flag=1;//开关初始为1,让子进程先发出SIGUSR2信号给父进程while(1){if(flag==0){kill(pid,SIGUSR2);flag=1;}}}else if(pid==0){num=1;//子进程从一开始计数signal(SIGUSR2,func2);while(1){if(flag==0){kill(getppid(),SIGUSR1);flag=1;}}}
}
结果:

相关文章:
Linux中sigaction函数和SIGCHLD信号的使用
sigaction函数: 函数说明:注册一个信号处理函数 函数原型:int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 函数参数: signum:捕捉的信号act:传入参数,…...
【MySQL】操作库 —— 表的操作 -- 详解
一、增加表 1、创建表 mysql> create database [if not exists] table_name ( -> field1 datatype, -> field2 datatype, -> field3 datatype -> ) character set 字符集 collate 校验规则 engine 存储引擎; 注意 :最后一行也可以写成&#x…...
ZigBee学习——在官方例程实现组网
✨Z-Stack版本:3.0.2 ✨IAR版本:10.10.1 ✨这篇博客是在善学坊BDB组网实验的基础上进行完善,并指出实现的过程中会出现的各种各样的问题! 善学坊教程地址: ZigBee3.0 BDB组网实验 文章目录 一、基础工程选择二、可能遇…...
ES实战--wildcard正则匹配exists过滤字段是否存在
wildcard 通配符中的 * 表示任意数量的字符 ?表示任意单个字符 #正则匹配 GET /wildcard-test/_search {"query": {"wildcard": {"title": {"wildcard": "ba*n"}}} } #响应:"hits": {"total": {"…...
C++学习:二分查找
二分查找的前提 库函数只能对数组进行二分查找。 对一个数组进行二分查找的前提是这个数组中的元素是单调的。 一般为单调不减,当然如果是单调不增也可以(需要修改比较函数) 例如: [1,5,5,9,18]是单调的 [1 , 9, 9,…...
语言与科技创新(大语言模型对科技创新的影响)
1.语言因素对科技创新的影响 科技创新中的语言因素至关重要,具体体现在以下几个方面: 科技文献交流: 英语作为全球科学研究的通用语言,极大地推动了科技成果的国际传播与合作。在国际上,科学家们在发表论文、报告研究…...
【C语言】简单贪吃蛇实现保姆级教学!!!
关注小庄 顿顿解馋૮(˶ᵔ ᵕ ᵔ˶)ა 新年快乐呀小伙伴 引言: 小伙伴们应该都有一个做游戏的梦吧?今天让小庄来用C语言简单实现一下我们的童年邪典贪吃蛇,顺便巩固我们的C语言知识,请安心食用~ 文章目录 贪吃蛇效果一.游戏前工作…...
rtt设备io框架面向对象学习-uart设备
目录 1.uart设备基类2.uart设备基类的子类3.初始化/构造流程3.1设备驱动层3.2 设备驱动框架层3.3 设备io管理层 4.总结5.使用 1.uart设备基类 此层处于设备驱动框架层。也是抽象类。 在/ components / drivers / include / drivers 下的serial.h定义了如下uart设备基类 struc…...
Innodb下修改事务工作流程(buffer pool、redo log、undolog)
1、在Buffer Pool中读取数据:当InnoDB需要更新一条记录时,首先会在Buffer Pool中查找该记录是否在内存中。如果没有在内存中,则从磁盘读取该页到Buffer Pool中。 2、记录UndoLog:在修改操作前,InnoDB会在Undo Log中记…...
redis为什么使用跳跃表而不是树
Redis中支持五种数据类型中有序集合Sorted Set的底层数据结构使用的跳跃表,为何不使用其他的如平衡二叉树、b树等数据结构呢? 1,redis的设计目标、性能需求: redis是高性能的非关系型(NoSQL)内存键值数据…...
【matalab】基于Octave的信号处理与滤波分析案例
一、基于Octave的信号处理与滤波分析案例 GNU Octave是一款开源软件,类似于MATLAB,广泛用于数值计算和信号处理。 一个简单的信号处理与滤波分析案例,说明如何在Octave中生成一个有噪声的信号,并设计一个滤波器来去除噪声。 首…...
Elasticsearch:特定领域的生成式 AI - 预训练、微调和 RAG
作者:来自 Elastic Steve Dodson 有多种策略可以将特定领域的知识添加到大型语言模型 (LLM) 中,并且作为积极研究领域的一部分,正在研究更多方法。 对特定领域数据集进行预训练和微调等方法使 LLMs 能够推理并生成特定领域语言。 然而&#…...
HarmonyOS—UI 开发性能提升的推荐方法
开发者若使用低性能的代码实现功能场景可能不会影响应用的正常运行,但却会对应用的性能造成负面影响。本章节列举出了一些可提升性能的场景供开发者参考,以避免应用实现上带来的性能劣化。 使用数据懒加载 开发者在使用长列表时,如果直接采用…...
84 CTF夺旗-PHP弱类型异或取反序列化RCE
目录 案例1:PHP-相关总结知识点-后期复现案例2:PHP-弱类型对比绕过测试-常考点案例3:PHP-正则preg_match绕过-常考点案例4:PHP-命令执行RCE变异绕过-常考点案例5:PHP-反序列化考题分析构造复现-常考点涉及资源…...
Duilib List 控件学习
这是自带的一个示例; 一开始运行的时候List中是空的,点击Search按钮以后就填充列表框; 先看一下列表框列头是在xml文件中形成的; <List name="domainlist" bkcolor="#FFFFFFFF" ... menu="true"> <ListHeader height="24…...
详细了解Node.js的配置与使用!
详细了解Node.js的配置与使用! Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它允许开发者在服务器端运行 JavaScript,从而实现全栈 JavaScript 开发。本文将介绍 Node.js 的配置和 npm 的应用。 一、Node.js 配置 下载与安装 首先&…...
OpenCV 移动最小二乘图像变形
文章目录 一、简介二、实现代码三、实现效果参考文献一、简介 在现实生活中,我们常常应用一些刚性的变换来实现物体的旋转平移,对于非刚性的变换我们都没有在意,其实这种变换也是无处不在的,如我们经常看的动画就可以通过一些非刚性的变换达到一些非常夸张的效果。这里,我…...
【深度学习】S2 数学基础 P4 概率论
目录 基本概率论概率论公理随机变量 多个随机变量联合概率条件概率贝叶斯定理求和法则独立性 期望与方差小结 基本概率论 机器学习本质上,就是做出预测。而概率论提供了一种量化和表达不确定性水平的方法,可以帮助我们量化对某个结果的确定性程度。 在…...
跟我学c++中级篇——静态多态
一、多态 Polymorphism,多态。学习过c的人如果不知道多态,基本上就是打入c内部的C程序员了。在前边曾经对多态进行过分析,对其中的虚函数(虚表等)也进行过较为详细的说明。 多态其实非常好理解,不要硬扣书…...
设计模式--桥接模式(Bridge Pattern)
桥接模式(Bridge Pattern)是一种结构型设计模式,它主要是用于将抽象部分与实现部分分离,使它们可以独立地变化。 桥接模式主要包含以下几个角色: Abstraction(抽象类):定义抽象类的…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Selenium 查找页面元素的方式
Selenium 查找页面元素的方式 Selenium 提供了多种方法来查找网页中的元素,以下是主要的定位方式: 基本定位方式 通过ID定位 driver.find_element(By.ID, "element_id")通过Name定位 driver.find_element(By.NAME, "element_name"…...
