信号的捕捉(操作部分)

目录

信号集和信号屏蔽字

信号集

信号屏蔽字

信号位操作函数

sigemptyset

sigaddset

sigismember

sigprocmask

sigpending

手动操作让2号信号屏蔽打印pending

信号处理函数sigaction


我们继续来学习信号的捕捉

信号集和信号屏蔽字

信号集

信号集是存储一组信号的集合,本质也是一个位图,信号集可以存储未决信号,屏蔽信号,所以信号屏蔽字是信号集的一种,我们可以自己创建一个信号集,其类型为sigset_t,sigset_t类型是系统内置类型。

信号屏蔽字

信号屏蔽字Signal Mask进程级 的一个 位掩码,用于指定 哪些信号应该被阻塞(屏蔽),即这些信号在进程解除屏蔽之前不会被递送到进程。每个进程都有一个 信号屏蔽字,它是一个 位图(bitmask),每一位对应一个 信号(如 SIGINTSIGTERM 等):

信号屏蔽字是进程(或线程)的一个状态变量,它决定了当前进程(或线程)正在屏蔽哪些信号。其本质是位图,注意信号屏蔽字就是 Block 表(阻塞信号集),block表的另一种说法是信号屏蔽字。所以说我们创建信号屏蔽字本质不就是创建一个信号集吗。

对进程信号捕捉机制进行操着无非就是操作那三张表,无非就是在改位图的比特位,但是我们不建议直接进行位操作的修改,所以Linux内置了不少的函数帮助我们完成这个事。

信号位操作函数

sigemptyset

sigemptyset 是一个 POSIX 信号处理相关的函数,它用于初始化信号集(sigset_t),并将其清空,即不包含任何信号。

我们如果自己创建一个新的信号集,这时如果只是单纯的sigset_t set,这时信号集set往往是乱码的,不能直接用,我们就需要调用这个函数将其所以的bit位都制成0。

参数是一个指针。返回值如上:

sigaddset

sigaddset 是一个 POSIX 信号处理相关的函数,用于向信号集 (sigset_t) 中添加一个指定的信号。

通过sigaddset添加的信号编号signum,它会修改内部的比特位表示,使得对应信号的比特位变为 1(表示该信号已被添加),是一个由0置1的过程

sigismember

sigismember 是一个 POSIX 信号处理函数,用于检查某个信号是否在指定的 sigset_t 信号集中。

我们值得关注一下这个返回值。

上面这几个是本次试验要用到的函数,我们操作信号主要还是修改进程中的pending表和block表,有没有直接可以对着这两个表进行操作的函数。

sigprocmask

sigprocmask 是 POSIX 提供的信号管理函数,用于修改或查询进程的信号屏蔽字(signal mask),即进程当前阻塞的信号集。被屏蔽的信号不会被进程接收,直到解除屏蔽。

就是操作block表的,具体这么操作取决于此函数的第一个参数how的传参。

how有三种传参方式如上,也就是说可以直接用我们自己创建的信号屏蔽字取代进程中的block。

第二个参数set是输入型参数,第三个参数oldset是输出型参数,用于存放调用前进程的信号屏蔽字。

sigpending

sigpending 用于获取当前进程被阻塞但未被递达的信号(即挂起的信号),就是获取进程的pending表。

这个set参数是输出型参数。

为什么没有修改和替换等的操作,我们每次发信号不就在修改pending表吗,OS接收到信号pending表对应位置不就置1了吗,在 Linux 及 POSIX 规范中,进程的 挂起信号集pending)是内核自动管理的,用户态程序不能直接修改它。这是出于信号处理的设计原则系统安全性的考虑,记得9号信号是不能删除/替代/修改的,如果pending表可以让人随便修改,那不就违背了9号信号的原则了吗?

手动操作让2号信号屏蔽打印pending

我们接着的操作就是运用上面的函数,先屏蔽2号信号,然后获取pending表,只打印其中的32位,接着发送2号信号就可以看到2号信号pending效果,为什么要先屏蔽呢,我们不能让2号信号使得程序终止。

#include<iostream>
#include<unistd.h>
#include<signal.h>
using namespace std;
void PrintPending(const sigset_t& pending)
{cout << "curr pending list [" << getpid() << "]: ";for (int i = 31; i > 0; i--){//判断pending表中是否存在此编号的信号if (sigismember(&pending, i)){cout << 1;}else if (sigismember(&pending, i) == 0){cout << 0;}//忽略对i无效的情况}cout << endl;
}
int main()
{//1.屏蔽2号信号sigset_t block;sigset_t oblock;//初始化sigemptyset(&block);sigemptyset(&oblock);//添加2号信号进block,只是添加还没有设置进内核sigaddset(&block, 2);//设置进内核sigprocmask(SIG_SETMASK, &block, &oblock);while (true){//循环获取并打印内核的pending表sigset_t pending;sigpending(&pending);//打印pending表的前32位(只关注32位信号)PrintPending(pending);sleep(1);}return 0;
}

这里sigprocmask的how可以使用上面的直接替换也可以使用SIG_BLOCK添加。至此我们就完成了先写入2号信号,然后内核屏蔽,打印pending的过程。

可以看到发送2号信号之后pending表果然有记录了(由0变1),为什么没有退出呢,因为block表里面已经事先屏蔽了该信号。

接着我们体验2号信号从屏蔽到接触的过程,接触2号信号只需要再次使用sigprocmask将保存原有block表的oblock替代之前的就可以了。

    //设置进内核sigprocmask(SIG_SETMASK, &block, &oblock);int cnt = 0;while (true){//循环获取并打印内核的pending表sigset_t pending;sigpending(&pending);//打印pending表的前32位(只关注32位信号)PrintPending(pending);sleep(1);cnt++;if (cnt == 15){cout << "解除对2号信号的屏蔽" << endl;//我们这次不关心旧的block表的值sigprocmask(SIG_SETMASK, &oblock, nullptr);}}return 0;
}

我们一旦解除了,2号信号一递达进程就被退出了,所以就停止了!!!

信号处理函数sigaction

sigactionLinux 中用来 处理信号(signal) 的系统调用,它比 signal() 更加强大和可靠。

也就是说sigaction具有和signal相同的功能,就是更改handler特定数组下标里面的内容。

和sigpromask的结构有点像,对一个编号为signum的信号进行act形式的捕捉,返回原有的捕捉方法oldact,这个act和oldact的类型是一个结构体,名字和函数名一样。

我们可以看到,sa_sigaction这个是用来捕捉实时信号的,我们不用管,上面这个就是signal同款的捕捉方式函数,同样的使用函数名传参(回调函数),sa_flag不用管,sa_mask是自定义屏蔽信号的位图,就是想屏蔽更多信号就sigaddset到这里。

sa_mask 里添加的信号会在 信号处理函数运行时自动屏蔽,防止嵌套执行,所以sigaddset添加进入sa_mask的信号就不需要再sigprocmask进内核了,算是一种自动添加到block表的行为

不过:

sigaction 里的 sa_mask 作用是:

当 信号(SIGINT )被触发时(某种行为如Ctrl+C),handler() 运行的这段时间,sa_mask 里的信号会自动被屏蔽,直到 handler() 结束。所以这种屏蔽是暂时的,当信号没有被捕捉或者处理完了不调用handler了就不生效了。

#include<iostream>
#include<signal.h>
#include<unistd.h>
using namespace std;void Printblock()
{sigset_t set;sigset_t olset;sigemptyset(&set);sigemptyset(&olset);sigprocmask(SIG_BLOCK, &set, &olset);for (int i = 31; i >= 0; i--){if (sigismember(&olset, i)){cout << 1;}else{cout << 0;}}cout << endl;
}
void handler(int signo)
{while (1){cout << "get a sig: " << signo << endl;Printblock();sleep(1);}
}int main()
{struct sigaction act, oact;act.sa_handler = handler;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, 3);sigaddset(&act.sa_mask, 4);sigaddset(&act.sa_mask, 5);sigaddset(&act.sa_mask, 6);::sigaction(2, &act, &oact);while (true){Printblock();//等待信号到来pause();}
}

可以看到确实如此!!!

当handler方法正在被处理时,此时2号信号的pending表一定是1,但是如果假设handler处理时间很久并且有指令调用系统调用使CPU陷入内核,此时又来了很多个2号信号,OS不允许信号处理方法进行嵌套,当某个信号正在被处理时又来了这个信号,操作系统就不会将pending表其再置1了,转而将block表的对应位置1表示阻塞,等信息处理完自动解除阻塞状态。

pending表由1->0的过程表示信号被处理完了,这个过程是在调用handler表的处理函数之前就置0了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/36978.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CIR-Net:用于 RGB-D 显著性目标检测的跨模态交互与优化(问题)

摘要 问题一&#xff1a;自模态注意力优化单元和跨模态加权优化单元什么意思&#xff1f; 1 优化中间件结构的作用 位置&#xff1a;位于编码器和解码器之间 输入&#xff1a;编码器提取的RGB特征&#xff0c;深度特征以及RGB-D特征。 输出&#xff1a;经过优化的RGB&…

Linux驱动开发基础(can)

目录 1.can的介绍 2.can的硬件连接 2.1 CPU自带can控制器 2.2 CPU没有can控制器 3.电气属性 4.can的特点 5.can协议 5.1 can的种类 5.2 数据帧 5.2.1 标准数据帧格式 5.3.1 扩展数据帧格式 5.3 遥控帧 5.4 错误帧 5.5 过载帧 5.6 帧间隔 5.7 位填充 5.8 位时…

【北京迅为】iTOP-RK3568开发板OpenHarmony系统南向驱动开发UART接口运作机制

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

【嵌入式学习】时钟 - 边缘触发锁存器

目录 ## 时钟 ## 带边缘触发的寄存器 ## 优化内存走线 ## 画16位的内存 ## 时钟 波特率&#xff1a;一分钟说几个字 clock统一计算机内部的节奏&#xff0c;clock频率越高cpu速度越快 触发&#xff1a;电压的突变&#xff1b;下降沿&#xff1a;高变低&#xff1b;上升沿…

Linux C/C++编程——线程

线程是允许应用程序并发执行多个任务的一种机制&#xff0c;线程参与系统调度。 系统调度的最小单元是线程、而并非进程。 线程包含在进程之中&#xff0c;是进程中的实际运行单位。一个线程指的是进程中一个单一顺序的控制流&#xff08;或者说是执行路线、执行流&#xff09;…

CAN通信转TCP/IP通信协议解析

背景&#xff1a;最近项目开发受限于开发版只有一路CAN口和多个CAN通信对象的帧ID一样&#xff0c;考虑采用转换模块将CAN通信转成TCP/IP通信&#xff0c;间接实现获取CAN报文数据的目的。 1. 转换模块协议 首先想到的是采购周立功他家的多路CAN通信转TCP/IP通信模块&#xf…

vue:组件的使用

Vue&#xff1a;组件的使用 1、什么是组件 1.1、传统方式开发的应用 一个网页通常包括三部分&#xff1a;结构&#xff08;HTML&#xff09;、样式&#xff08;CSS&#xff09;、交互&#xff08;JavaScript&#xff09;。在传统开发模式下&#xff0c;随着项目规模的增大&a…

强大的AI网站推荐(第一集)—— Devv AI

网站&#xff1a;Devv AI 号称&#xff1a;最懂程序员的新一代 AI 搜索引擎 博主评价&#xff1a;我的大学所有的代码都是使用它&#xff0c;极大地提升了我的学习和开发效率。 推荐指数&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x…

gradle-8.13

gradle-8.13 稍微看了下&#xff0c;基于Maven改造的 https://gradle.org/install/https://github.com/gradle/gradle-distributions/releaseshttps://github.com/gradle/gradle-distributions/releases/download/v8.13.0/gradle-8.13-all.zip https://github.com/gradle/gra…

网络安全——SpringBoot配置文件明文加密

XTHS&#xff1a;第一步、XTHS&#xff1a;第二步、XTHS&#xff1a;第三步、XTHS&#xff1a;第四步 &#xff01;就可以实现了。&#xff08;但是前提&#xff0c;你要先对你的文本进行加密&#xff0c;然后按照ENC(加密文本)&#xff0c;放到配置文件中&#xff09; 一、前言…

wsl2配置xv6全解(包括22.04Jammy)

文章目录 获取xv6源代码Ubuntu20.04 Version安装指令成功测试参考MIT2021年官方文档 24.04 Version安装指令成功测试参考MIT2024年官方文档 Ubuntu 22.04没有官方文档&#xff1f; 配置大体流程1. 卸载原本qemu&#xff08;如果之前安装了&#xff09;2. clone qemu官方源代码&…

【机器学习-分类算法】

比如将一张图片按尺寸识别分类为横向或者纵向两类就是二分类问题 设x轴为图像的宽、y轴为图像的高&#xff0c;那么把训练数据展现在图上就是这样的: 若增加更多的数据集有: 如果只用一条线将图中白色的点和黑色的点分开,那么: 分类的目的就是找到这条线,就可以根据点在线…

java项目之基于ssm的疫苗预约系统(源码+文档)

项目简介 疫苗预约系统实现了以下功能&#xff1a; 用户信息管理 负责管理系统用户的信息。 疫苗信息管理 负责管理疫苗的相关信息。 疫苗类型管理 负责管理不同种类疫苗的信息。 疫苗留言管理 负责管理用户关于疫苗的留言和反馈。 公告信息管理 负责发布和管理与疫苗相关…

游戏引擎学习第171天

回顾并计划今天的内容 昨天&#xff0c;我们在处理一项任务时暂停了&#xff0c;当时的目标非常清晰&#xff0c;但由于时间限制&#xff0c;我们将其分成了两个部分。我们首先完成了运行时部分&#xff0c;而今天要处理的是资产打包部分。这项任务涉及改进字体系统&#xff0…

跨平台RTSP高性能实时播放器实现思路

跨平台RTSP高性能实时播放器实现思路 目标&#xff1a;局域网100ms以内超低延迟 一、引言 现有播放器&#xff08;如VLC&#xff09;在RTSP实时播放场景中面临高延迟&#xff08;通常数秒&#xff09;和资源占用大的问题。本文提出一种跨平台解决方案&#xff0c;通过网络层…

Deepseek+飞书实现简历分析建议+面试题

步骤一&#xff1a;创建多维表格 点击云文档点击主页点击新建创建多维表格 步骤二&#xff1a;创建列 首先将多余的列进行删除 创建简历内容列&#xff0c;类型使用文本&#xff0c;目的是将简历内容复制进来 创建AI列&#xff1a;简历分析、简历建议、面试题 点击确定后&…

Linux基础开发工具--gdb的使用

目录 安装准备&#xff1a; 1. 背景 2. 开始使用 3. 做一个Linux第一个小程序&#xff0d;进度条 安装准备&#xff1a; 对于gdb的学习使用&#xff0c;为了方便大家学习&#xff0c;我建议大家先安装一个cgdb进行学习&#xff0c;这样方便观察操作与学习gdb。 用以下…

leetcode热题100道——两数之和

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…

某公司制造业研发供应链生产数字化蓝图规划P140(140页PPT)(文末有下载方式)

详细资料请看本解读文章的最后内容。 资料解读&#xff1a;某公司制造业研发供应链生产数字化蓝图规划 在当今制造业数字化转型的浪潮中&#xff0c;企业信息化建设成为提升竞争力的关键。本资料围绕 XX 公司的信息化建设展开&#xff0c;涵盖业务战略、信息化路线图、各领域系…

【总结篇】java多线程,新建线程有几种写法,以及每种写法的优劣势

java多线程 新建线程有几种写法,以及每种写法的优劣势 [1/5]java多线程 新建线程有几种写法–继承Thread类以及他的优劣势[2/5]java多线程-新建线程有几种写法–实现Runnable接口以及他的优劣势[3/5]java多线程 新建线程有几种写法–实现Callable接口结合FutureTask使用以及他的…