Linux:进程通信(二)信号的保存

目录

一、信号的处理是否是立即处理的?

 二、信号如何保存

1、阻塞、未决、递达

2、信号集

3、信号集操作函数

4、sigprocmask函数

5、sigpending 函数


上篇文章我们讲解了信号的产生:Linux:进程信号(一)信号的产生

接下来我们来看一下信号的保存

一、信号的处理是否是立即处理的?

        信号的处理是否立即进行,取决于信号的类型、进程的当前状态,以及进程对信号的处理策略。

  1. 信号的优先级:某些信号需要立即处理,比如 SIGKILL(强制终止进程)和 SIGSTOP(暂停进程)。这些信号一旦被发送给目标进程,操作系统会立即采取行动。其他信号,比如 SIGTERMSIGUSR1,可能会被延迟处理,特别是在进程有更高优先级的任务在进行时。

  2. 进程的状态:如果进程正在内核态(如系统调用期间),信号的处理可能被延迟,直到进程回到用户态。此外,如果进程正在被其他信号阻塞,或处于某种临界区,信号也可能被暂时推迟。

  3. 信号的阻塞和掩码:进程可以通过信号掩码来阻止某些信号的立即处理。操作系统将这些阻塞的信号放入进程的信号队列中,直到进程解除阻塞。

  4. 信号处理函数:进程可以设置信号处理函数。当信号到达时,如果进程当前正在运行中,它可能会等到适当的时机(如下一个调度周期)才调用信号处理函数。

 二、信号如何保存

信号需要被进程记录下来,以确保即使在信号到达时进程无法立即处理时,信号也不会丢失。这种记录通常发生在进程的信号队列中。

信号队列是内核为每个进程维护的一个数据结构,用于存储已经到达但尚未被处理的信号。当进程接收到信号时,内核将信号放入进程的信号队列中,然后等待进程在适当的时机处理它们。这样做可以确保即使进程在信号到达时处于某种阻塞状态,也能够在稍后的时候处理这些信号。

信号队列通常存储在内核的内存中,并且对于每个进程都有一个单独的信号队列。进程可以使用系统调用来检查它的信号队列,并且可以对信号队列进行操作,比如阻塞或解除阻塞某些信号。

1、阻塞、未决、递达

实际执行信号的处理动作称为信号递达(Delivery)
信号从产生到递达之间的状态,称为信号未决(Pending)
进程可以选择阻塞 (Block ) 某个信号。
被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作.
注意 , 阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。

 如下图所示

比特位的位置表示信号的编号,比如图中是三号信号,三号信号产生后,未决信号集对应位置为1,内核来判断是否应该被处理,如果被处理则置为0 。而如果该信号被阻塞,那么就不会被处理,直到阻塞解除。

那么信号集如何管理呢:

2、信号集

sigset_t

sigset_t 用于表示一组信号,通常用于表示被阻塞的信号集合或者待处理的信号集合。

在内部实现上,sigset_t 可以被看作是一个位图,其中每个位代表一个信号。如果某个位被设置为 1,则表示对应的信号被包含在集合中;如果被设置为 0,则表示对应的信号不在集合中。

这种位图的表示方式非常高效,因为它可以用很小的内存空间表示很多信号。通常情况下,sigset_t 的大小被限制在一个字(通常是 32 位或 64 位)的大小范围内,所以它适用于表示系统支持的信号数量。

sigset_t可以本质上被视为一个位图 ,关于位图我们前面也介绍过:C++:Hash应用【位图与布隆过滤器】

3、信号集操作函数

sigset_t 类型对于每种信号用一个 bit 表示 有效 无效 状态 , 至于这个类型内部如何存储这些 bit 则依赖于系统实现, 从使用者的角度是不必关心的 , 使用者只能调用以下函数来操作 sigset_ t 变量
#include <signal.h>
int sigemptyset(sigset_t *set);
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);
  • sigemptyset(sigset_t *set): 此函数用于将信号集合 set 清空,即将所有信号从集合中移除,使得 set 表示一个空集。调用此函数后,set 中不包含任何信号。

  • sigfillset(sigset_t *set): 此函数用于将信号集合 set 填满,即将所有信号添加到集合中,使得 set 包含系统支持的所有信号。调用此函数后,set 中包含所有可能的信号。

  • sigaddset(sigset_t *set, int signo): 此函数用于向信号集合 set 中添加指定的信号 signo。添加成功后,set 中将包含 signo 代表的信号。

  • sigdelset(sigset_t *set, int signo): 此函数用于从信号集合 set 中删除指定的信号 signo。删除成功后,set 中将不再包含 signo 代表的信号。

  • sigismember(const sigset_t *set, int signo): 此函数用于检查指定的信号 signo 是否包含在信号集合 set 中。如果 signo 存在于 set 中,则返回非零值;否则返回 0。

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

4、sigprocmask函数

调用函数 sigprocmask 可以读取或更改进程的信号屏蔽字 ( 阻塞信号集 )
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
返回值:若成功则为0,若出错则为-1
如果调用 sigprocmask 解除了对当前若干个未决信号的阻塞 , 则在 sigprocmask 返回前 , 至少将其中一个信号递达。
通过man sigprocmask命令可以看到

how参数的取值:

我们通过代码来测试一下:

#include<signal.h>
#include<iostream>
#include <sys/types.h>
#include <unistd.h>int main()
{sigset_t set,oset;sigemptyset(&set);sigemptyset(&oset);sigaddset(&set,SIGINT);//屏蔽2号信号sigprocmask(SIG_BLOCK,&set,&oset);while(true){std::cout<<"我是"<<getpid()<<"号进程"<<std::endl;sleep(1);}return 0;
}

运行代码后我们使用Ctrl+c发出2号信号,没有停止

因为2号信号已经被屏蔽,就算使用kill命令发出也是一样的:

 

那么我们来解除阻塞后会不会恢复正常呢:

#include<signal.h>
#include<iostream>
#include <sys/types.h>
#include <unistd.h>int main()
{sigset_t set,oset;sigemptyset(&set);sigemptyset(&oset);sigaddset(&set,SIGINT);//屏蔽2号信号sigprocmask(SIG_BLOCK,&set,&oset);while(true){std::cout<<"我是"<<getpid()<<"号进程"<<std::endl;sleep(20);sigprocmask(SIG_UNBLOCK,&set,&oset);//20秒后解除阻塞}return 0;
}

可以看到

在未解除前,我们发送2号信号是没用的,但在20秒后,会自动处理2号信号退出。

因为阻塞并不是处理,信号依旧保持未决,暂时不递达,直到解除对信号的阻塞。

需要注意的是,9号信号是不会被屏蔽的,大家可以在上面代码的基础上测试。

5、sigpending 函数

sigpending 函数用于获取当前被阻塞但是仍然排队等待传递给进程的信号集合。也就是未决信号集

int sigpending(sigset_t *set);
调用成功则返回 0, 出错则返回 -1。
我们使用下列代码来测试:
#include<signal.h>
#include<iostream>
#include <sys/types.h>
#include <unistd.h>void printsigset(sigset_t *set)
{for(int i=31;i>=0;i--){if(sigismember(set,i)){std::cout<<"1";}else{std::cout<<"0";}}std::cout<<std::endl;
}
int main()
{sigset_t set,oset;sigemptyset(&set);sigemptyset(&oset);sigaddset(&set,SIGINT);//屏蔽2号信号sigprocmask(SIG_BLOCK,&set,&oset);while(true){std::cout<<"我是"<<getpid()<<"号进程"<<std::endl;sigpending(&oset);printsigset(&oset);sleep(1);}return 0;
}

运行后可以看到:

当收到2号进程后,信号集对应的位置置为1,但是没有被执行,因为2号信号被阻塞了,按Ctrl-\仍然可以终止程序,因为SIGQUIT信号没有阻塞。

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

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

相关文章

ResponseHttp

文章目录 HTTP响应详解使用抓包查看响应报文协议内容 Response对象Response继承体系Response设置响应数据功能介绍Response请求重定向概述实现方式重定向特点 请求重定向和请求转发比较路径问题Response响应字符数据步骤实现 Response响应字节数据步骤实现 HTTP响应详解 使用抓…

适用于 Windows 的免费恢复软件:前 7 个解决方案对比

Windows计算机上的数据恢复可能是一项简单或艰巨的任务&#xff0c;具体取决于您使用的软件。 软件的质量及其功能将决定将恢复多少数据、文件的完整性、扫描存储的深度以及整个过程在时间和恢复成功率方面的整体效率。 如果您想了解一些适用于 Windows的最佳免费取消删除软件…

Adobe Illustrator 2024 for Mac:矢量图形设计软件

Adobe Illustrator 2024 for Mac是一款专为Mac用户设计的行业标准矢量图形设计软件。该软件以其卓越的性能和丰富的功能&#xff0c;为设计师和艺术家们提供了一个全新的创意空间。 作为一款矢量图形软件&#xff0c;Adobe Illustrator 2024 for Mac支持创建高质量的矢量图形&a…

如何利用工作流自定义一个AI智能体

选择平台 目前已经有不少大模型平台都提供自定义智能体的功能&#xff0c;比如 百度的文心 https://agents.baidu.com/ 阿里的百炼平台 https://bailian.console.aliyun.com/。 今天再来介绍一个平台扣子&#xff08;https://www.coze.cn/&#xff09;&#xff0c;扣子是…

翔云优配官网美股市场分析问界回应M7事故四大疑问

问界再次新M7 Plus山西高速事故。 4月26日下午,山西运城曾有一辆问界新M7 Plus车辆(以下简称“事故车辆”)在高速行驶时和一辆高速洒水车追尾,碰撞后车辆起火,造成三人遇难,该事故引发了广泛关注。 翔云优配以其专业的服务和较低的管理费用在市场中受到不少关注。该平台提供了…

效率跨越式提升的工农业对机器人专业的需求

需求 需要用人的地方一定会逐步收缩。 原来需要人的地方也会逐步被机器人取代。 机器人这个专业最强的悖论就是可以部分取代人。 此处&#xff1a;用人的地方是指“工农业”&#xff0c;包括工业和农业。 机器人工程行业算制造业吗 机器人工程终身学习和工作计划 趋势 工匠…

安卓动态加载view

目录 前言一、addview1.1 addView 的重载方法1.2 在 LinearLayout 中的使用1.2.1 addView(View child)方法的分析&#xff1a;1.2.2 addView(View child, int index)方法的分析&#xff1a;1.2.3 小结 1.3 在 RelativeLayout 中的使用 二、addContentview2.1 测试 12.2 测试 22…

华为OD机试【最大N个数与最小N个数的和】(java)(100分)

1、题目描述 给定一个数组&#xff0c;编写一个函数来计算它的最大N个数与最小N个数的和&#xff0c;需要对数组进行去重。 说明&#xff1a; ● 数组中数字范围[0, 1000] ● 最大N个数与最小N个数不能有重叠&#xff0c;如有重叠&#xff0c;输入非法返回-1 ● 输入非法返回-…

【解决方案】Can‘t exec “locale”: No such file or directory

【解决方案】Cant exec “locale”: No such file or directory 还可能出现的错误&#xff1a; 1. 报错原因&#xff1a; 缺少ldconfig 2. 解决方案&#xff1a; sudo apt-get download libc-bin dpkg -x libc-bin*.deb unpackdir/ sudo cp unpackdir/sbin/ldconfig /sbin/ s…

明星中药企业系列洞察(一)丨官宣提价后股价涨幅近15%,百年老字号佛慈制药如何焕发力量?

近日&#xff0c;佛慈制药发布公告称&#xff0c;鉴于原材料以及生产成本上涨等原因&#xff0c;公司对主营中成药产品的出厂价进行调整&#xff0c;平均提价幅度为9%。提价消息释出后&#xff0c;资本市场给出了态度&#xff1a;佛慈制药股价连续两天累计上涨近15%。佛慈制药近…

Docker安装部署一本通:从Linux到Windows,全面覆盖!(网络资源精选)

文章目录 📖 介绍 📖🏡 说明 🏡⚓️ 相关链接 ⚓️📖 介绍 📖 随着容器技术的飞速发展,Docker已成为现代软件开发和运维不可或缺的工具。然而,不同平台下的Docker安装部署方式各异,这常常让初学者感到困惑。本文将为您详细梳理各平台下Docker的安装部署方法,帮…

组件通信-(父子组件通信)

目录 一、什么是组件通信 二、组件关系的分类 三、组件通信解决方案 四、父传子 五、子传父 一、什么是组件通信 组件通信&#xff0c;就是指组件与组件之间的数据传递。组件的数据是独立的&#xff0c;无法直接访问其他组件的数据。如果想使用其他组件的数据&#xff0c;…

cron表达式xxljob

Cron格式说明 | | | | | | | | | | | | | — 年 (range: 1970-2099) | | | | | ------- 周 (range: 1&#xff5e;7&#xff09; | | | | ----------- 月(range: 1&#xff5e;12) | | | --------------- 日(range: 1&#xff5e;31) | | ------------------- 时(range: 0…

软件FMEA的时机:架构设计、详设阶段——FMEA软件

免费试用FMEA软件-免费版-SunFMEA 软件FMEA&#xff08;故障模式与影响分析&#xff09;是一种预防性的质量工具&#xff0c;旨在识别软件中可能存在的故障模式&#xff0c;并分析其对系统性能、安全性和可靠性的影响。在软件开发生命周期中&#xff0c;选择适当的时机进行FME…

工业光源环形系列一高亮条形光源特点

产品特点 ◆可以根据检测需求随意调整照射角度&#xff1b; ◆可以根据检测需求选择光源颜色&#xff1b; ◆多个条形光源可以自由组合&#xff1b; ◆使用大功率贴片灯珠&#xff0c;亮度高&#xff1b; ◆灯珠上面增加透镜&#xff0c;照射距离更远

【Unity动画系统】动画层级(Animation Layer)讲解与使用

如何使用Unity的Animation Layer和Avater Mask把多个动画组合使用 想让玩家持枪行走&#xff0c;但是手里只有行走和持枪站立的动作。 Unity中最方便的解决办法就是使用动画层级animation layer以及替身蒙版avatar mask。 创建一个动画层级 Weight表示权重&#xff0c;0的话则…

使用 OpenNJet 分分钟完成打地鼠小游戏部署

文章目录 OpenNJet应用引擎什么是应用引擎什么是OpenNJet独特优势技术架构 OpenNJet安装RPM安装 部署打地鼠小游戏配置OpenNJet部署打地鼠小游戏启动 NJet访问打地鼠小游戏 总结 今天阿Q打算使用OpenNJet应用引擎来部署一下我们的打地鼠小游戏。在开始部署之前&#xff0c;我们…

教你快速记录每日待办事项,并提醒自己按时完成不忘记

在忙碌的日常生活中&#xff0c;我们经常会面临待办事项繁杂、时间紧迫的困扰。为了更高效地管理时间和任务&#xff0c;我们需要一个能够快速记录并准时提醒我们完成待办事项的工具。此时&#xff0c;敬业签这类的待办软件就成为了很多人的首选工具。 敬业签是一款功能强大的…

Raft共识算法图二解释

下面是有关Raft协议中不同术语和概念的翻译及解释&#xff1a; 术语和概念&#xff1a; 任期号&#xff08;term number&#xff09;&#xff1a;用来区分不同的leader。前一个日志槽位的信息&#xff08;prelogIndex&#xff09;&#xff1a;这是前一个日志条目的索引&#…