Linux--阻塞信号--信号集--0104 05

news2024/12/24 0:20:53

1. 阻塞信号

1.1 信号其他相关常见概念

  • 实际执行信号的处理过程称为信号递达。
  • 信号从产生到递达之间的状态称为信号未决。
  • 进程可以选择阻塞(Block)某个信号。
  • 被阻塞的信号保持在未决状态,直至进程解除对该信号的阻塞,才执行递达操作。
  • 阻塞和忽略是不同的,阻塞是一种状态,忽略是一种处理信号的方法

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

每个信号都有两个标志位,表示阻塞(block)和未决(pending),还有一个函数指针以表示信号的处理动作。

1.3 信号处理的过程

  • 当进程接受到一个信号(2号信号)时,在其pcb结构体内的“信号标记图”中的pending位图中对应的比特位就会由0置1。
  • 当人为设置了阻塞信号(2号信号和3号信号)时,“信号标记图”中的block位图中对应的比特位就会由0置1。
  • 当进程收到信号,并且该信号并未被阻塞时,才会去找handler中对应的函数指针。SIG_DFL和SIG_IGN是两个宏。

(int)handler[signal]==0 ;//执行默认动作 处理完毕

(int)handler[signal]==1;//执行忽略动作,处理完毕

如果上述两个都不满足,才会去调用函数。

handler[signal]();

2. sigset_t 类型

由于信号需要的是标记位哦,非0即1。操作系统给了我们一个新的数据类型sigset_t,用户可以直接使用该类型与自定义类型和内置类型没有区别。它本质上就是一个位图,但是不允许用户进行位操作(~ / & / |),添加/修改位图的值需要通过OS系统提供的接口。

一个sigset_t 类型被称为信号集。

3.信号集操作函数

#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() 初始化该信号集,全部置0。
  • sigfillset() 初始化该信号集,全部置1。
  • sigaddset() 将对应信号编号的比特位置1。
  • sigdelset() 将对应信号编号的比特位置0 。
  • sigismember() 查看在set中 signo编号信号状态是0还是1 。

3.1 sigprocmask

调用sigprocmask可以读取或者更改进程的阻塞信号集

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

set : 是我们自己通过sigaddset() 和 sigdelset() 设置好的 希望操作的信号形成的信号集

oset : 是一个输出型参数。方便我们需要恢复之前的信号屏蔽集。

 how参数的选项及说明

SIG_BLOCK

set包含了我们希望添加到阻塞信号集的信号

mask=mask|set

SIG_UNBLOCK

set包含了我们希望从阻塞信号集解除的信号

mask=mask&~mask

SIG_SETMASK

设置当前信号屏蔽字为set所指向的值,相当

于mask=set

 使用

int main()
{
    sigset_t bset,obset;
    sigset_t pending;
    sigemptyset(&bset);
    sigemptyset(&obset);
    sigaddset(&bset,2);//添加想要操作的(2号)信号
    int n=sigprocmask(SIG_BLOCK,&bset);//将2号信号设为阻塞状态
    //obset里面保存的没修改之前的信号集
    assert(n==0); //不为0直接报错
    (void)n;
    int m=sigprocmask(SIG_SETMASK,&obset,nullptr);
    //因为obset 只设置了2号信号 所以可以接着用以解除2号信号的屏蔽
    assert(m==0);
    (void)m;
    return 0;
}

3.2 sigpending

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

static void showPending(sigset_t &pending)
{
    for (int sig = 1; sig <= 31; sig++)
    {
        if (sigismember(&pending, sig))
            std::cout << "1";
        else
            std::cout << "0";
    }
    std::cout << std::endl;
}
int main()
{
    sigset_t pending;
    sigemptyset(&pending);
    sigaddset(&bset, 2);
    int n = sigprocmask(SIG_BLOCK, &bset, &obset);
    assert(n == 0);
    (void)n;
    while (true)
    {
        //获取当前进程的pending信号集
        sigpending(&pending);
        showPending(pending);
        sleep(1);
    }
    return 0;
}

 4.验证问题

4.1 对所有信号进行捕捉 如何终止程序

写一个for循环对每个信号都进行捕捉。

void catchSig(int signum)
{
    std::cout << "获取一个信号: " << signum << std::endl;
}
int main()
{
    for(int sig = 1; sig <= 31; sig++) signal(sig, catchSig);
    while(true) sleep(1);
    return 0;
}

 结论 9号信号无法被捕捉

Bash: kill -9 pid

依然可以杀死程序

4.2 观察pending信号集的变化

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
//请放到Linux环境下执行代码
static void handler(int signum)
{
	std::cout << "捕捉 信号: " << signum << std::endl;
	// 不要终止进程,exit
}
static void showPending(sigset_t& pending)
{
	for (int sig = 1; sig <= 31; sig++)
	{
		if (sigismember(&pending, sig))
			std::cout << "1";
		else
			std::cout << "0";
	}
	std::cout << std::endl;
}


int main()
{
	 //捕捉2号信号
	 signal(2, handler);
	 sigset_t bset, obset,pending;
	 //初始化
	 sigemptyset(&bset);
	 sigemptyset(&obset);
	 sigemptyset(&pending);
	 //添加要进行屏蔽的信号
	 sigaddset(&bset, 2 /*sigint*/);
	 //设置set到内核中
	 int n = sigprocmask(SIG_BLOCK, &bset, &obset);
	 assert(n == 0);
	 (void)n;

	 std::cout << "block 2 号信号成功...., pid: " << getpid() << std::endl;
	 // 打印当前进程的pending
	 int count = 0;
	 while (true)
	 {
	     //获取pending信号集
	     sigpending(&pending);
	     //显示pending信号集中
	     showpending(pending);
	     sleep(1);
	     count++;
	     if (count == 20)
	     {
	         std::cout << "解除对于2号信号的block" << std::endl;
	         int n = sigprocmask(SIG_SETMASK, &obset, nullptr);
	         assert(n == 0);
	         (void)n;
	     }
	 }
}

 运行结果

4.3 阻塞所有信号 如何终止程序

结论 无法阻塞9号信号和19号信号

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

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

相关文章

Qt—事件处理

Qt中&#xff0c;事件作为一个对象&#xff0c;继承自QEvent类&#xff0c;常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等。Qt中&#xff0c;任何QObject子类示例都可以接收和处理事件。实际编程中通常实现部件的paintEvent&#xff08;&#xff0…

百度语音+自动驾驶感知+深度学习平台技术解析

HIEV快讯&#xff08;文/戒僧&#xff09;本文将解析三部分技术内容&#xff0c;出自百度2023 Create大会-技术开放日&#xff1a; •百度如何用“手机全双工语音交互”改善使用导航应用的体验 •如何用“上帝视角”BEV技术提升汽车的自动驾驶能力 •如何用百度自研的深度学习平…

k8s常见错误

master节点初始化失败 出现这个原因是因为&#xff0c;我们之前有执行过初始化的命令&#xff0c;然后初始化的时候就会产生一些文件&#xff0c;和占用端口&#xff0c;然后当你再次初始化的时候&#xff0c;就会提示你有些文件已经存在和端口正在被使用&#xff0c;所以我们…

年末高压叠加“阳”后虚弱,双重压力下的测试者们该何去何从

在2022年的最后一个月&#xff0c;国家放开管控&#xff0c;发布“新十条”&#xff0c;不查核酸&#xff0c;不看健康码&#xff0c;以前闻之色变的“小阳人”&#xff0c;十几天后&#xff0c;遍地皆是。 相信大家对这段时间的经历难以忘怀&#xff0c;在刚放开的时候&#x…

【论文阅读笔记】EndoL2H: Deep Super-Resolution for Capsule Endoscopy

论文地址&#xff1a;https://arxiv.org/abs/2002.05459 代码地址&#xff1a;https://github.com/CapsuleEndoscope/EndoL2H 论文小结 顾名思义&#xff0c;本文是胶囊内窥镜领域的超分算法。本文的网络结构是条件对抗网络 空间attention块的方式&#xff0c;实现8倍、10倍和…

不要再被骗了,解密短视频里追剧看电影都能赚钱的坑。

不要再被骗了,解密短视频里追剧看电影都能赚钱的坑。 最近刷短视频刷到了好多抖音追剧看电影每天收几百&#xff0c;还有截图&#xff0c;还有怎么实操的视频。 关键不是刷到一个两个&#xff0c;是几十个还有越来越多的趋势。 都说新入门实操&#xff0c;终于忍不住&#x…

LeetCode刷题Day05——链表(链表元素删除、相交、环形链表)

文章目录一、删除链表中的倒数第n个节点二、链表相交三、环形链表一、删除链表中的倒数第n个节点 题目链接&#xff1a;19.删除链表中的倒数第n个节点 /*** <pre>* 最简单的方法显然是先遍历一遍链表&#xff0c;知道长度后重新遍历一次就可以找到指定节点了&#xff0…

WebDAV之葫芦儿·派盘+DAVx⁵

DAVx⁵ 支持WebDAV方式连接葫芦儿派盘。 支持移动设备远程同步,是不是比NAS更便捷?并且这款软件最为关键的还是支持各种协议,让你能够在跨平台上面同步安卓和苹果上面的内容,你可以在服务器上面进行一些简单的内容管理,快来试试DAVx⁵与派盘的最佳组合吧。 DAVx⁵是一款…

LeetCode:18. 四数之和

18. 四数之和1&#xff09;题目2&#xff09;思路3&#xff09;代码4&#xff09;结果1&#xff09;题目 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &…

Codeforces Round #772 (Div. 2)

A. Min Or Sum 题目链接&#xff1a;Problem - A - Codeforces 样例输入&#xff1a; 4 3 1 3 2 5 1 2 4 8 16 2 6 6 3 3 5 6样例输出&#xff1a; 3 31 6 7题意&#xff1a;给你一个长度为n的数组&#xff0c;我们可以对这个数组进行操作&#xff0c;每次操作可以选择两个不…

ThinkPHP5之文件包含审计分析(五)

说明 该文章来源于同事lu2ker转载至此处&#xff0c;更多文章可参考&#xff1a;https://github.com/lu2ker/ 文章目录说明0x00 环境准备0x01 测试代码0x02 代码分析0x03 总结参考链接&#xff1a;Mochazz/ThinkPHP-Vuln/ 影响版本&#xff1a;5.0.0<ThinkPHP5<5.0.18 、…

Java - JIT即时编译

java前端编译器和后端编译器的作用Java前端编译器&#xff1a;javac 编译&#xff0c;在程序运行前&#xff0c;将 源文件 转化为 字节码 即 .class 文件Java 程序最初只能通过解释器解释执行&#xff0c;即 JVM 对字节码逐条解释执行&#xff0c;因此执行速度比较慢。字节码与…

【SAP Abap】SAP Flight 航班系统数据模型简介(SCARR、SPFLI、SFLIGHT、SBOOK等)

SAP Flight 航班系统数据模型简介&#xff08;SCARR、SPFLI、SFLIGHT、SBOOK等&#xff09;1、本文目的2、数据模型3、查看模型数据4、生成演示数据5、模型应用1、本文目的 SAP ABAP 系统都会自带 Flight 航班系统数据模型&#xff0c;其大量应用于 SAP ABAP 帮助文档、系统 D…

移动安全总结 2019

声明 本文是学习移动安全总结 2019. 下载地址 http://github5.com/view/1223而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 序言 随着2019年的逝去&#xff0c;二十一世纪第二个十年也已随之结束。回顾过去的十年&#xff0c;我们的生活随着科技的进…

养老院人员定位方案125K芯片AS3933/SI3933/GC3933/PAN3501

随着社会老龄化&#xff0c;高龄化&#xff0c;空巢化和病残化的迅速发展&#xff0c;将使得越来越多的老人住进养老院。虽养老院数量越来越多&#xff0c;但养老院人也越来越多&#xff0c;给现有的养老管理上带来压力&#xff0c;由于服务人员有限&#xff0c;无法及时顾及到…

【LeetCode每日一题】——89.格雷编码

文章目录一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【解题思路】七【题目提示】八【时间频度】九【代码实现】十【提交结果】一【题目类别】 数学 二【题目难度】 中等 三【题目编号】 89.格雷编码 四【题目描述】 n 位格雷码序列 是一…

举个栗子!Tableau 技巧(249):为文本表中的不同度量设置不同颜色

使用文本表呈现数据时&#xff0c;通常会用颜色的深浅来代表度量的数值大小。单一度量很容易实现&#xff0c;但多个度量的情况&#xff0c;很多数据粉反馈不知道如何实现。 如下示例&#xff0c;在为不同度量设置了不同颜色后&#xff0c;的确既美观又直观。 具体该如何实现呢…

进制转换 2进制转10进制 10进制转2进制

觉得有用的&#xff0c;HXD们请点个赞●▽● 10进制转2进制&#xff08;以十进制100转换为二进制为例子&#xff1a;&#xff09; 方法一&#xff08;除2取余数&#xff0c;倒叙摆列&#xff0c;高位补零 &#xff09; 100/250余0&#xff1b; 50/225余0&#xff1b; 25/21…

Allegro174版本新功能介绍之改变菜单字体大小

Allegro174版本新功能介绍之改变菜单字体大小 Allegro在升级到174的时候,默认的字体是非常小的,如下图 看起来十分费劲 启动界面 菜单界面 但是174是支持把把这些字体调大的,具体操作如下 选择Setup

git远程仓库使用流程

git远程仓库使用流程远程仓库使用流程远程仓库介绍远程仓库使用流程如何将本地文件夹关联远程仓库多人开发配置流程远程仓库SSH配置远程仓库使用流程总结git分支使用流程分支介绍1.2-分支使用流程远程仓库使用流程 Git命名作用详细描述git clone克隆远程仓库代码把服务器的项目…