Linux——进程信号(二)

目录

1、阻塞信号

1.1、信号其他相关常见概念

1.2、在内核中的表示

1.3、sigset_t

1.4、信号集操作函数

2、捕捉信号

2.1、内核如何捕捉信号

5.2、sigaction


1、阻塞信号

1.1、信号其他相关常见概念

实际执行信号的处理动作被称为信号递达(Delivery);

信号从产生到递达之间的状态,称为信号未决(Pending);

进程可以选择阻塞(Block)某个信号;

被阻塞的信号产生时将保持在未决状态,直到进程接触对此信号的阻塞,才执行递达的动作;

注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

1.2、在内核中的表示

信号在内核中的表示示意图:

每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中,SIGHUP信号未阻塞也未生产过,当它递达时执行默认处理动作。

SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有接触阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。

SIGQUIT信号未产生过,一旦生产SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。

如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?

POSIX.1允许系统递送改信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次而实时信号在递达之前产生多次可以依次放在一个队列里。

1.3、sigset_t

从上面的图可以看出,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞表示也是这样表示的。因此,未决标志和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态,在阻塞信号集中“有效”和“无效”的含义是该信号是否被阻塞,而在未决信号集中“有效”和“无效”的含义是是该信号是否处于未决状态。后面会详细介绍各种信号集的操作。阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的屏蔽应该理解为阻塞而不是忽略。

1.4、信号集操作函数

 sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现,从使用者的角度是不必关心的,使用者只能调用以下函数来操作sigset_ t变量,而不应该对它的内部数据做任何解释,比如用printf直接打印sigset_t变量是没有意义的。

#include <signal.h>//初始化set所指向的信号集,使其中所有的信号对应bit清零
//表示该信号集不包含任何有效信号
int sigemptyset(sigset_t *set);//初始化set所指向的信号集,使其中所有信号的对应bit置位
//表示该信号集的有效信号包括系统支持的所有信号
int sigfillset(sigset_t *set);//将某个信号添加到信号集中
int sigaddset(sigset_t *set, int signo);//将某个信号从信号集删除
int sigdelset(sigset_t *set, int signo);//判断某个信号是否在信号集中
int sigismember(const sigset_t *set, int signo);

注意:在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。

这四个函数都是成功返回0,出错返回-1。sigismember是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,若包含则返回1,不包含则返回0,出错返回-1。

如果要通过信号集对进程的pending、block表进行相关设置,还需要调用sigprocmask。

#include<signal.h>int sigprocmask(int how, const sigset_t *set, sigset_t *oset);返回值:若成功则为0,若出错则为-1

调用函数sigprocmask可以读取或更改进程的信号屏蔽字(阻塞信号集)。

如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。

#include<signal.h>int sigpending(sigset_t *set);读取当前进程的未决信号集,通过set参数传出。调用成功则返回0,出错则返回-1。

下面用这几个函数做一个实验:

1、先把2号信号屏蔽

2、kill或者键盘发送2号信号,可以预见2号信号不会被递达

3、2号信号将会一直被阻塞,一定一直在pending中

4、使用sigpending获取当前进程的pending信号集

#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <asm-generic/signal.h>void printsigset(sigset_t *set)
{int i = 0;for (;i<32;i++){//判断指定信号是否在目标集合中if (sigismember(set,i)){printf("1");}else {printf("0");}}printf("\n");
}int main()
{//定义信号集对象,并清空初始化sigset_t set, oset;sigemptyset(&set);sigemptyset(&oset);sigaddset(&set, SIGINT);//设置阻塞信号集,阻塞SIGINT信号sigprocmask(SIG_BLOCK, &set, &oset);sigset_t pending;while(1){sigemptyset(&pending);sigpending(&pending);printsigset(&pending);sleep(1);}return 0;
}

可以看到我们发送信号前二号信号为0,发送后2号信号为1,因为当前信号无法被递达所以处于pending状态,就被pending捕获并打印出来了。


2、捕捉信号

2.1、内核如何捕捉信号

如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了 SIGQUIT 信号的处理函数 sighandler 。当前正在执行 main 函数,这时发生中断或异常切换到内核态。在中断处理完毕后要返回用户态的main函数之前检查到有信号 SIGQUIT 递达。内核决定返回用户态后不是恢复 main 函数的上下文继续执行,而是执行 sighandler 函数,sighandler 和 main 函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是两个独立的控制流程。 sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复 main 函数的上下文继续执行了。

5.2、sigaction

#include <signal.h>

int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);

sigaction 函数可以读取和修改与指定信号相关联的处理动作。调用成功则返回0,出错则返回 -1 。signo 是指定信号的编号。若 act 指针非空,则根据 act 修改该信号的处理动作。若oact指针非空,则通过oact传出该信号原来的处理动作。act 和 oact 指向sigaction结构体:
将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动作,赋值为一个函数指针表示用自定义函数捕捉信号,或者说向内核注册了一个信号处理函数,该函数返回值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。

当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么它会被阻塞到当前处理结束为止。如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处
理函数返回时自动恢复原来的信号屏蔽字。

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>struct sigaction act, oact;
void sigcb(int signo)
{printf("get a signal: %d\n", signo);sigaction(SIGINT, &oact, NULL);
}int main()
{memset(&act, 0, sizeof(act));memset(&oact, 0, sizeof(oact));act.sa_handler = sigcb;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT, &act, &oact);while(1){printf("I am a process!\n");sleep(1);}return 0;
}

这样便捕捉到了一次信号,第二次不再捕捉可以正常退出。

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

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

相关文章

迈向容错新时代!PASQAL发布最新技术路线图

内容来源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 编辑丨慕一 编译/排版丨沛贤 深度好文&#xff1a;1200字丨8分钟阅读 近日&#xff0c;法国中性原子量子计算公司PASQAL发布了最新技术路线图&#xff0c;概述了其在硬件、业务场景用例及进一…

v3-admin-vite 整合pont

需求 目前后端的Admin模板使用的是v3-admin-vite&#xff0c;需要整合pont接口&#xff0c;方便前后端统一一体化开发 安装PONT 按照官方的文档&#xff0c;将pont engine安装好&#xff0c;然后在项目根目录执行pont start。注意生成代码路径要修改一下&#xff0c;因为v3-a…

【区间、栈】算法例题

目录 六、区间 48. 汇总区间 ① 49. 合并区间 ② 50. 插入区间 ② 51. 用最少数量的箭引爆气球 ② 七、栈 52. 有效的括号 ① 53. 简化路径 ② 54. 最小栈 ② 55. 逆波兰表达式求值 ② √- 56. 基本计算器 ③ 六、区间 48. 汇总区间 ① 给定一个 无重复元素 的 …

外键约束

目录 外键约束 对数据表进行初期设计&#xff0c;暂时不使用外键 验证限制三 验证级联删除 设置级联更新 Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 外键约束 外键约束主要是在父子表关系中体现的一种约束操作。…

matlab 基于小波变换的油气管道泄露信号检测

1、内容简介 略 71-可以交流、咨询、答疑 基于小波变换的油气管道泄露信号检测 去噪、小波变换、油气管道泄露、信号检测 2、内容说明 摘 要&#xff1a; 油气管道泄漏会造成严重危害&#xff0c;因此&#xff0c;亟需寻找一种能快速检测油气管道信号的技术。传统的 傅里…

Java多线程实战-CompletableFuture异步编程优化查询接口响应速度

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️本系列源码仓库&#xff1a;多线程并发编程学习的多个代码片段(github) &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正…

远程桌面安卓版下载 安卓远程控制免费版

远程桌面安卓版下载与安卓远程控制免费版的应用解析 随着移动互联网的快速发展&#xff0c;远程桌面应用逐渐成为了许多用户、特别是技术爱好者和商务人士的必备工具。它们不仅可以在电脑上实现远程控制&#xff0c;还能将这种功能延伸到移动设备上&#xff0c;如安卓手机和平…

R语言中的常用基础绘图函数 直方图,箱线图,条形图,散点图

目录 R语言中的绘图参数 绘图函数 1.plot函数绘制散点图 2.hist函数绘制直方图 如何修饰直方图? 如何在直方图上标注各组频数&#xff1f; 使用text函数把某些信息标注在直方图上 如何在直方图上添加概率密度曲线&#xff1f; 3.boxplot函数绘制箱线图 4.barplot函数…

一、MySQL基础学习

目录 1、MySQL启动2、MySQL客户端连接3、SQL3.1、SQL语句分类3.2、DDL&#xff08;数据库定义语言&#xff09;3.2.1、操作数据库3.2.2、操作数据表 3.3、DML&#xff08;数据库操作语言&#xff09;3.3.1、增加 insert into3.3.2、删除 delete3.3.3、修改 update 3.4、DQL&…

idea error java:compilation failed:internal java compiler error

idea中编译运行maven项目报错如下 idea error java:compilation failed:internal java compiler error 尝试如下操作 注意&#xff1a;jdk8 需要设置4个地方 1.首先打开File->Project Structure中的Project&#xff0c;将SDK和language level都设置一致&#xff0c;如下…

Jackson 2.x 系列【4】对象映射器 ObjectMapper

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.0.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. 案例演示2.1 创建对象2.2 写入2.3 读取 3. 泛型擦除 1. 概述 在前两篇文…

IO多分复用

#include<myhead.h> #define SER_PORT 8888 //服务器端口号 #define SER_IP "192.168.65.131" //服务器IPint main(int argc, const char *argv[]) {//1、创建一个套接字int sfd -1;sfd socket(AF_INET, SOCK_STREAM, 0); //参数1&#xff1a;…

北斗卫星引领农机春耕新时代

北斗卫星引领农机春耕新时代 随着现代科技的快速发展&#xff0c;北斗卫星成为了农业领域不可或缺的利器。在农机自动驾驶系统的引领下&#xff0c;农机正逐渐实现自主操作&#xff0c;为农民节省了大量的时间和精力&#xff0c;并最大限度地提高了农作物的产量和质量。 北斗…

30天拿下Rust之错误处理

概述 在软件开发领域&#xff0c;对错误的妥善处理是保证程序稳定性和健壮性的重要环节。Rust作为一种系统级编程语言&#xff0c;以其对内存安全和所有权的独特设计而著称&#xff0c;其错误处理机制同样体现了Rust的严谨与实用。在Rust中&#xff0c;错误处理通常分为两大类&…

词令微信小程序怎么添加到我的小程序?

微信小程序怎么添加到我的小程序&#xff1f; 1、找到并打开要添加的小程序&#xff1b; 2、打开小程序后&#xff0c;点击右上角的「…」 3、点击后底部弹窗更多选项&#xff0c;请找到并点击「添加到我的小程序」&#xff1b; 4、添加成功后&#xff0c;就可以在首页下拉我的…

迈入编程世界:C 语言初体验

写在前面&#xff1a;OK啊&#xff0c;前面我们介绍了C语言开发环境的搭建&#xff0c;今天我们再来初步的认识一下C语言&#xff0c;了解C语言的基础框架、数据的表现形式以及输入和输出。 文章特点&#xff1a;不会很正经&#xff0c;不会很学术&#xff0c;不会很理论&#…

J4G企业通讯ip电话 sip对讲主机 停车场对讲主机

J4G企业通讯ip电话 sip对讲主机 停车场对讲主机 SV-J4G 是一款企业级彩屏网络电话&#xff0c;具有高清语音&#xff0c;320x240 2.8英寸彩屏&#xff0c;支持千兆以太网&#xff0c;12个SIP账号&#xff0c;支持PoE供电&#xff0c;支持外接EHS无线耳机&#xff0c;三方电话会…

C++有关内存的那些事

个人主页&#xff1a;PingdiGuo_guo 收录转栏&#xff1a;C干货专栏 前言 本篇博客是讲解关于C内存的一些知识点的。 文章目录 前言 1.内存函数 1.1memcpy函数 1.2memmove函数 1.3 memset函数 2.各数据类型占用 2.1bool类型 2.2char类型 2.3short、int、long类型及整数…

京东商品信息采集API商品价格商品详情图主图抓取接口key(提供测试入口)

item_get 获得JD商品详情item_search 按关键字搜索商品item_search_img 按图搜索京东商品&#xff08;拍立淘&#xff09;item_search_shop 获得店铺的所有商品item_history_price 获取商品历史价格信息item_recommend 获取推荐商品列表buyer_order_list 获取购买到的商品订单列…

CMake笔记之GLOB和GLOB_RECURSE的使用方法

CMake笔记之GLOB和GLOB_RECURSE的使用方法 —— 杭州 2024-03-19 夜 文章目录 CMake笔记之GLOB和GLOB_RECURSE的使用方法1.GLOB使用方法2.GLOB对比GLOB_RECURSE 1.GLOB使用方法 在 CMake 中&#xff0c;file(GLOB ...) 命令用于将匹配特定模式的文件列表赋值给变量。这可以用…