Linux信号:信号的保存

news2024/11/24 11:12:20

目录

一、信号在内核中的表示

 二、sigset_t

2.1sigset_t的概念和意义

2.2信号集操作数

三、信号集操作数的使用

3.1sigprocmask

3.2sigpending

3.3sigemptyset

四、代码演示


一、信号在内核中的表示

实际执行信号的处理动作称为信号 递达(Delivery)
信号从产生到递达之间的状态,称为信号 未决(Pending)
进程可以选择 阻塞 (Block ) 某个信号。
被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
注意,阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作。
信号在内核中的表示示意图
每个信号都有两个标志位分别表示阻塞(block)和未决(pending),还有一个函数指针表示处理动作。信号产生时,内核在进程控制块中设置该信号的未决标志,直到信号递达才清除该标志。在上图的例子中
如上图所示:
SIGHUP信号未阻塞也未产生过,当它递达时执行默认处理动作。
SIGINT信号产生过,但正在被阻塞,所以暂时不能递达。虽然它的处理动作是忽略,但在没有解除阻塞之前不能忽略这个信号,因为进程仍有机会改变处理动作之后再解除阻塞。
SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。
如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

 二、sigset_t

2.1sigset_t的概念和意义

Linux中,常用的信号有31个,内核中则存在一个类似于位图的方式来对该进程的block,peding进行表示,由于不存在0号信号,所以信号就从1号位置开始到31,如果该位置上为1则表示该信号当前存在,为0则表示不存在。

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

2.2信号集操作数

sigset_t类型对于每种信号用一个bit表示“有效”或“无效”状态,至于这个类型内部如何存储这些bit则依赖于系统实现,从使用者的角度是不必关心的,使用者只能调用以下函数来操作sigset_ t变量,而不应该对它的内部数据做任何解释,比如用printf直接打印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初始化set所指向的信号集,使其中所有信号的对应bit清零,表示该信号集不包含 任何有效信号。
函数sigfillset初始化set所指向的信号集,使其中所有信号的对应bit置位,表示 该信号集的有效信号包括系统支持的所有信号。
注意,在使用sigset_ t类型的变量之前,一定要调 用sigemptyset或sigfillset做初始化,使信号集处于确定的状态。初始化sigset_t变量之后就可以在调用sigaddset和sigdelset在该信号集中添加或删除某种有效信号。

三、信号集操作数的使用

3.1sigprocmask

调用函数 sigprocmask 可以读取或更改进程的信号屏蔽字 ( 阻塞信号集)。
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 
返回值:若成功则为0,若出错则为-1
如果oset是非空指针,则读取进程的当前信号屏蔽字通过oset参数传出。如果set是非空指针,则 更改进程的信号屏蔽字,参数how指示如何更改。如果oset和set都是非空指针,则先将原来的信号 屏蔽字备份到oset里,然后根据set和how参数更改信号屏蔽字。假设当前的信号屏蔽字为mask,下表说明了how参数的可选值。
如果调用sigprocmask解除了对当前若干个未决信号的阻塞,则在sigprocmask返回前,至少将其中一个信号递达。

3.2sigpending

#include <signal.h>

sigset_t pendig;
int n=sigpending(&pending);
读取当前进程的未决信号集,通过set参数传出。调用成功则返回0则n=0,出错则返回-1则n=-1。

3.3sigemptyset

清空sigset_t类型内部的数据。

sigset_t pending;
sigemptyset(&pending);
考虑到各个平台的不同,这种方式可以很好解决在栈上生成随机值的情况

四、代码演示

#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <cassert>
#include <sys/wait.h>

void PrintSig(sigset_t &pending)
{
    std::cout << "Pending bitmap: ";
    for (int signo = 31; signo > 0; signo--)
    {
        if (sigismember(&pending, signo))//判断该信号是否在信号集中
        {
            std::cout << "1";
        }
        else
        {
            std::cout << "0";
        }
    }
    std::cout << std::endl;
}

void handler(int signo)
{
    sigset_t pending;
    sigemptyset(&pending);
    int n = sigpending(&pending); // 正在处理2号信号
    assert(n == 0);

    // 3. 打印pending位图中的收到的信号
    std::cout << "递达中...: ";
    PrintSig(pending); // 0: 递达之前,pending 2号已经被清0. 1: pending 2号被清0一定是递达之后
    std::cout << signo << " 号信号被递达处理..." << std::endl;
}

int main()
{
    // 对2号信号进行自定义捕捉 --- 不让进程因为2号信号而终止
    signal(2, handler);

    // 1. 屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigaddset(&block, 2); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中

    // 0. for test: 如果我屏蔽了所有信号呢???
    // for(int signo = 1; signo <= 31; signo++) // 9, 19号信号无法被屏蔽, 18号信号会被做特殊处理
    //     sigaddset(&block, signo); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中
    // 1.1 开始屏蔽2号信号,其实就是设置进入内核中
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    assert(n == 0);
    // (void)n; // 骗过编译器,不要告警,因为我们后面用了n,不光光是定义
    std::cout << "block 2 signal success" << std::endl;
    std::cout << "pid: " << getpid() << std::endl;
    int cnt = 0;
    while (true)
    {
        // 2. 获取进程的pending位图
        sigset_t pending;
        sigemptyset(&pending);
        n = sigpending(&pending);
        assert(n == 0);

        // 3. 打印pending位图中的收到的信号
        PrintSig(pending);
        cnt++;

        // 4. 解除对2号信号的屏蔽
        if (cnt == 20)
        {
            std::cout << "解除对2号信号的屏蔽" << std::endl;
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock); // 2号信号会被立即递达, 默认处理是终止进程
            assert(n == 0);
        }
        // 我还想看到pending 2号信号 1->0 : 递达二号信号!
        sleep(1);
    }

    return 0;
}

通过以上代码所演示的现象我们也可以验证两个结论:

1、递达信号的时候一定会把对应的pending位图清0。

2、先清0,再递达。

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

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

相关文章

Day48 Javascript详解

Day48 Javascript详解 文章目录 Day48 Javascript详解一、什么是javascript二、javascript特点三、 Javascript的历史四、Javascript vs Java五、JS的基本数据类型六、JS基本数据类型的特殊点七、数组 一、什么是javascript JavaScript是一种高级的、解释型的编程语言&#xf…

automa:循环元素的一个示例,取TME结合插件实现自动下载音乐。

因为tme没提供批量下载音乐的功能。我找到了一个插件可以下载。但需要点击播放时&#xff0c;才能感 知。 我原来用python写了一个&#xff0c;能实现&#xff0c;这想把他移植到automa上&#xff0c;同时想使用循环元素的方法&#xff0c;避免不必要的时间浪费。 开始。首先…

揭秘:水滴式粉碎机为何如此受欢迎

在粉碎机市场中&#xff0c;水滴式粉碎机以其D特的设计和G效的性能脱颖而出&#xff0c;成为众多用户的选择产品。那么&#xff0c;水滴式粉碎机究竟有何魅力&#xff0c;能够赢得如此广泛的赞誉呢&#xff1f; 首先&#xff0c;水滴式粉碎机的G效性能是其受欢迎的关键因素之一…

那些网络安全上的事实,很多人不见得知道!

明月发现不少小白对网络安全的认知几乎为零&#xff0c;甚至明月还碰到一个说 VPN 能彻底隐匿自己的&#xff0c;至于现在这帮动不动就利用 DDos/CC 攻击被人网站来推销境外高防服务器、高防 CDN 的老鼠屎们更是网络安全知识白痴的水平&#xff0c;破坏和攻击的水平完全取决于能…

阿里云oss存储直传回调服务的内网穿透

阿里云oss存储直传回调服务的内网穿透 前提 为什么在使用阿里云的oos直传的时候要使用内网穿透呢&#xff1f; 因为阿里云在使用回到服务的时候&#xff0c;要求访问的必须是外网&#xff0c;而我们的本地IPv4只是内网&#xff0c;无法被回调&#xff0c;所以我们需要使用内网…

【0007day】总体标准差、样本标准差和无偏估计

文章目录 总体标准差和样本标准差无偏估计无偏性与无偏估计量 总体标准差和样本标准差 一些表示上的差别。 总体标准差 样本标准差 两者的区别 样本方差为什么除以n-1? 这主要是由于样本的方差会低估总体的方差&#xff08;抽样的过程中&#xff0c;按照概率来说&#xff0…

融资融券利率4.0%!融资融券保证金比例和余额

融资融券利率最低是4.0%~5.0%&#xff0c;这是目前市场最低的利率水平&#xff0c;股票佣金万一。 各家券商的利率差异是较大的&#xff0c;现在无门槛利率是5%&#xff0c;根据投资者的资金量大小在4.0%~5%之间浮动&#xff0c;具体需要通过对应证券经理协商办理&#xff01;…

极空间部署本地最强私有化PDF工具箱『Stirling-PDF』

极空间部署本地最强私有化PDF工具箱『Stirling-PDF』 哈喽小伙伴们好&#xff0c;我是Stark-C~ 关注我的粉丝应该知道&#xff0c;我在前几天教大家怎么在NAS上部署本地最强私有化PDF工具箱『Stirling-PDF』&#xff1a; &#x1f53a;评论区好几位小伙伴都提到了极空间的部署…

当面试官问出“Unsafe”类时,我就知道这场面试废了,祖坟都能给你问出来!

一、写在开头 依稀记得多年以前的一场面试中&#xff0c;面试官从Java并发编程问到了锁&#xff0c;从锁问到了原子性&#xff0c;从原子性问到了Atomic类库&#xff08;对着JUC包进行了刨根问底&#xff09;&#xff0c;从Atomic问到了CAS算法&#xff0c;紧接着又有追问到了…

Github 2024-05-25 Rust开源项目日报Top10

根据Github Trendings的统计,今日(2024-05-25统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Svelte项目1TypeScript项目1Python项目1Go项目1Dart项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust…

基于地理坐标的高阶几何编辑工具算法(1)——目录

文章目录 背景目录效果相交面裁剪相离面吸附线分割面合并相交面合并相离面矩形绘制整形面 背景 在实际的地图编辑平台中&#xff0c;有一些场景是需要对几何面做修形操作&#xff0c;低效的做法是通过新增形点拖拽来实现。为了提高面几何的编辑效率&#xff0c;需要提供一些便…

社区医院|基于SprinBoot+vue的社区医院管理服务系统(源码+数据库+文档)

社区医院管理服务系统 目录 基于SprinBootvue的社区医院管理服务系统 一、前言 二、系统设计 三、系统功能设计 1系统功能模块 2管理员功能模块 3用户功能模块 4医生功能模块 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取…

XSS漏洞:pikachu靶场中的XSS通关

目录 1、反射型XSS&#xff08;get&#xff09; 2、反射性XSS&#xff08;POST&#xff09; 3、存储型XSS 4、DOM型XSS 5、DOM型XSS-X 6、XSS之盲打 7、XSS之过滤 8、XSS之htmlspecialchars 9、XSS之href输出 10、XSS之js输出 最近在学习XSS漏洞&#xff0c;这里使用…

文件上传安全指南:保护免受不受限制的文件上传攻击

文件上传安全指南&#xff1a;保护免受不受限制的文件上传攻击 在现代应用程序中&#xff0c;文件上传功能是一个常见且重要的部分。然而&#xff0c;这也为攻击者提供了潜在的攻击向量&#xff0c;尤其是不受限制的文件上传攻击。本文将详细介绍如何通过一系列安全措施来保护…

【C语言】指针(三)

目录 一、字符指针 1.1 ❥ 使用场景 1.2 ❥ 有关字符串笔试题 二、数组指针 2.1 ❥ 数组指针变量 2.2 ❥ 数组指针类型 2.3 ❥ 数组指针的初始化 三、数组指针的使用 3.1 ❥ 二维数组和数组名的理解 3.2 ❥ 二维数组传参 四、函数指针 4.1 ❥ 函数的地址 4.2 ❥ 函数…

3D瓦片地图组件上线|提供DEM数据接入,全方位呈现三维地图地形!

在用户调研中&#xff0c;我们了解到很多用户自身的可视化项目&#xff0c;需要在垂直空间上表现一些业务&#xff0c;例如&#xff1a;3D地形效果&#xff0c;数据底板建设等&#xff0c;而传统的地图效果不满足此用户需求。瓦片地图能够无限加载大地图&#xff0c;以更三维的…

【免费Web系列】大家好 ,今天是Web课程的第六天点赞收藏关注,持续更新作品 !

这是Web第一天的课程大家可以传送过去学习 http://t.csdnimg.cn/K547r 后端Web实战(IOCDI) 前言 Web开发的基础知识 &#xff0c;包括 Tomcat、Servlet、HTTP协议等&#xff0c;我们都已经学习完毕了&#xff0c;那接下来&#xff0c;我们就要进入Web开发的实战篇。在实战篇中…

正在直播:Microsoft Copilot Studio 新增支持Copilot代理、Copilot扩展等多项功能

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

如何在go语言中调用c语言代码

1.安装c语言编译器 要使用cgo&#xff0c;需要安装c语言编译器 gcc 2.检查CGO_ENABLED时候开启 使用以下命令查看&#xff1a; go env CGO_ENABLED 如果go env CGO_ENABLED被禁用(为0),需要将其设置为开启(为1) 3.编写c语言程序&#xff0c;并用go语言调用c语言程序 1&#xff…

机器学习之支持向量机SVM

支持向量机 概念 是supported vector machine&#xff08;支持向量机&#xff09;&#xff0c;即寻找一个超平面使样本分成两类&#xff0c;且间隔最大分类 分类 硬间隔 若样本线性可分&#xff0c;且所有样本分类正确情况下&#xff0c;寻找最大间隔&#xff0c;即硬间隔 若…