【Linux系统编程二十三】:(信号2)--信号的保存

news2024/11/25 13:23:02

【Linux系统编程二十三】:信号的保存

  • 一.信号的保存
    • 1.阻塞信号
    • 2.sigset_t类型(位图)
    • 3.block表
    • 4.handler表
    • 5.pending表
  • 二.实验验证
  • 三.信号的其他概念

一.信号的保存

信号发送本质上是操作系统发送信号,而进程PCB内部有一个位图用来表示是否接收到信号。如果接收到某个信号,该位置上的比特位就会由0置1。该位图我们称为penging表。

信号本质上其实就是一个一到三十一的数字,并且每一种信号都要有它对应的处理方法,即每一个信号都有它自己默认处理方法。所以进程的内核当中呢,还要为每一个信号维护一个叫做handler表。这个handle表它的类型是一个函数指针数组。里面都是信号对应默认处理方法。这里面的默认处理方法可以被捕捉变成自定义方法。
在这里插入图片描述

1.这个信号将来可以充当我们数组的下标,找到某一个位置。所以每个信号都对应着函数指针数组里的方法。
2.所以一旦信号产生了,那么我们直接拿着信号编号缩影一张表,就可以找到处理该信号的方式。

我们为什么要保存信号呢?

因为进程接收到信号之后,可能不会立即处理这个信号,信号不会被立即处理,那么就要有一个时间窗口,信号需要保存起来。

所以我们进程在运行时,一旦接收到信号了,那么对应的信号位图上的比特位就会由0置1,进程会处理这个信号,但是在合适的时候去处理。
所以信号暂时就在位图中保存起来。等进程忙完它的事情后,回来根据位图上的比特位来是否处理。这样信号就保存起来了。

不过信号的保存,不单单是信号位图的保存记录,还有信号阻塞,信号方法的保存。

1.阻塞信号

其实进程可以选择阻塞某个信号。什么意思呢?
进程接收到诸多信号后,可能不会立即处理,而是在适当的时候处理,但最后总归是会处理的。而如果一旦你把某些信号屏蔽了,在该信号没有被解除屏蔽之前,那么即便你收到了该信号。那么对应的信号也不会被操作系统系统进行处理。
还有如果没有产生一个信号,可以被屏蔽吗?可以被阻塞吗?
当然可以。屏蔽是一种状态。和你当前是否产生没关系。
所以在内核里进程还需要维护一张表叫做block表。它也是一张位图,比特位的位置决定的是信号的编号,比特位的内容是为0表示不屏蔽,为1表示屏蔽。那么阻塞也就意味着信号不会被处理。

在这里插入图片描述
理解普通信号时,我们只需要了解清楚三张表就可以,分别叫做pending表、block表和handler表。
pending表用来记录当前进程是否收到了信号,以及收到了哪些信号。
block表用来记录特定信号,那么是否被屏蔽。
handler表描述的是每一种信号所对的处理关系。

所以呢我们有了三张表,即两张位图和一个函数指针数组,就可以用来实现对普通信号的记录,保存相关的管理工作。

2.sigset_t类型(位图)

刚刚说的那pending表、handler表、block它都属于操作系统内部的内核数据结构。操作系统不相信任何用户,他不允许用户直接去修改。
如果用户你想改甚至想读获取这些表,对不起,不能直接读。
所以我们一定未来的访问这三张表是必须得有系统调用接口。

我们要获取这几个位图的时候,那么就注定了要在用户空间和内核空间内核空间和用户空间进行来回的数据拷贝。
所以数据拷贝时,我们就要在接口的参数设计上,要设置我们对应的输出出行参数。理论上获取内核里位图的信息,我们应该也用一个位图变量,将内核里的数据都拷贝到这个位图变量里来,然后由这个位图变量带出来。

如果用户想拿到你这个进程的pending表或block表,那么他怎么获取呢?
所以就必须要求操作系统给我们在应用上设计出一种数据类型。那么这个sigset_t类型呢,它就是我们传说中的位图结构。这是操作系统呢给我们提供了一种类型,叫做信号集类型。它是由操作系统给我们提供,在我们用户层可以直接使用的一种数据类型。

它属于系统级的数据类型,那么我们内部如何去呃存储对应的比特位呢?我们是不能直接用位操作获取位图里的比特位的!
在这里插入图片描述

如果我们将来拿到了进程的penging表、block表,以及我们拿到了我们所谓的sigset_t这样的位图类型,你也绝对不能自己再来进行位操作了啊,不允许你这么做,因为这是操作系统级别的类型。用户不能直接操作。

我们如果要修改对应的这这个sigset_t 位图,我们需要使用下面的这批系统调用。
在这里插入图片描述

3.block表

在这里插入图片描述
在这里插入图片描述
sigprocmask是用来读取或者更改进程的屏蔽信号的
它等价于其实就是阻塞信号器。它可以通过我们传递三个参数来达到对信号屏蔽字。

1.int how 第一个参数:是对block表的操作,你要干啥,是要新增一个屏蔽字还是删除一个屏蔽字呢?总共有三种选择:
①SIG_BLOCK:新增一个屏蔽字
②SIG_UNBLOCK:解除一个屏蔽字
③SIG_SETMAS:覆盖式的设置屏蔽字
2.sigset_t *set 第二个参数:是用来设置屏蔽字的,你要新增或者屏蔽哪个字段都在这个位图里设置,然后它会作为输入型参数配合how,设置到内核里。
3.sigset_t *oset 第三个参数:是将内核里的block位图先保存起来,未来可以还需要使用,保存就是为了恢复。所以作为输出型参数。

4.handler表

handler表本质上就是一个函数指针数组,它里面是信号对应的默认处理方法或者自定义方法。我们利用捕捉就可以获取到handler表里的方法。在这里插入图片描述
捕捉的方法有两种,一个是signal,一个是sigaction。
signal有两个参数,一个参数signum是信号的编号,另一个sighandler_t handler参数就是信号对应的处理方法。可以是操作系统提供的默认方法,也可以是自定义方法。我们应该在一开始就设置捕捉,而不是在最后,因为,捕捉信号只有接收到信号才会捕捉,没有接收到信号是不会捕捉的。如果放在最后,万一接收信号的时候,还没执行到捕捉代码那就不行了。所以捕捉代码最好写在一开头。

捕捉的本质就是去执行信号对应的方法。

在这里插入图片描述

5.pending表

在这里插入图片描述
这个sigpending函数就是用来获取pending位图里的比特位信息的。
它的参数是一个输出型参数,它的作用非常简单,它的作用就是要帮助我们把。调用进程它所对应的pending表给我们以位图的形式带出来。

二.实验验证

我们可以做一个验证:将二号信号屏蔽,然后发送二号信号,捕捉二号信号,再获取进程的pending表,最后再解除二号信号的屏蔽。会发生什么样的过程呢?

在这里插入图片描述

#include <iostream>
#include <signal.h>
#include <unistd.h>
using namespace std;

void PrintPending()
{
    sigset_t set;//位图变量,输出型参数

    sigpending(&set);//将penging表带出来

    for(int signo=1;signo<=31;signo++)
    {
        if(sigismember(&set,signo))//如果signo信号在set表里就为真
        cout<<"1";
        else
        cout<<"0";
    }
    cout<<endl;

}

void handler(int signo)
{
   cout<<"catch a signal "<<signo<<endl;
}
//保存信号主要靠三张表---block表,pending表和handler表

//现在我们想主动的屏蔽一个信号该如何实现呢?利用sigprocmask系统调用

int main()
{
    //0.首先对2号信号进行捕捉
    signal(2,handler);
    //1.对二号信号进行屏蔽
    //首先要信号是在位图里,所以我们需要利用位图来修改信号,需要位图变量。
    sigset_t bset,oset;//输入型参数,输出型参数,保存就是为了恢复
    sigemptyset(&bset);//对这两个位图变量初始化
    sigemptyset(&oset);
    sigaddset(&bset,2);//设置屏蔽字,将二号信号添加到bset位图里
    sigprocmask(SIG_SETMASK,&bset,&oset);//将best覆盖式屏蔽位图里的信号

    int cnt=0;
    //2.重复打印当前进程的pending表
    while(true)
    {
        PrintPending();
        sleep(1);
        cnt++;
        if(cnt==10)//解除2好信号屏蔽
        {
          
          cout<<"unblock signal"<<endl;
         sigprocmask(SIG_SETMASK,&oset,nullptr);//将原来的旧表覆盖
        }
    }
}

它的结果就是当发送2号信号时,进程并不会捕捉2号信号处理,打印pending表示,显示2号信号上的位图由0置1,说明接收到信号。但不处理。说明被屏蔽。
当解除屏蔽时,进程就会立即处理2号信号。

还有一件事,那就是并不是所有信号都可以被屏蔽,19号信号就不能捕捉也不能屏蔽。
在这里插入图片描述

所以信号最重要的就是这三个表了。而对这三个表的操作也很重要。
在这里插入图片描述

三.信号的其他概念

在这里插入图片描述
1.信号递达对应处理的是handler表。信号未决由pending表显示。信号阻塞由block表显示。
2.普通信号只会保存一次,即如果一次性发送许多同一的信号,该信号只会被保存一次。而如果该信号被屏蔽了,当发送许多相同信号,pending位图里只会记录一次。当该信号解除屏蔽,也只会执行一次方法。

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

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

相关文章

T-Dongle-S3开发笔记——创建工程

创建Hello world工程 打开命令面板 方法1&#xff1a;查看->命令面板 方法2&#xff1a;按F1 选择ESP-IDF:展示示例项目 创建helloworld 选择串口 选择芯片 至此可以编译下载运行了 运行后打印的信息显示flash只有2M。但是板子上电flash是W25Q32 4MB的吗 16M-bit

高级RGA(二):父文档检索器

在我之前写的<<使用langchain与你自己的数据对话>>系列博客中&#xff0c;我们介绍了利用大型语言模型LLM来检索文档时的过程和步骤&#xff0c;如下图所示&#xff1a; 我们在检索文档之前&#xff0c;通常需要对文档进行切割&#xff0c;然后将其存入向量数据库如…

用友时空KSOA UploadImage任意文件上传漏洞

漏洞描述 用友时空 KSOA 是根据流通企业前沿的IT需求推出的统的IT基础架构&#xff0c;它可以让流通企业各个时期建立的 IT 系统之间彼此轻松对话。由于用友时空设备开放了文件上传功能&#xff0c;但未鉴权且上传的文件类型、大小、格式、路径等方面进行严格的限制和过滤&…

企业知识库在跨地域团队协作中的价值

随着全球化进程的不断加速&#xff0c;越来越多的企业开始面临跨地域协作的挑战。在这种背景下&#xff0c;企业知识库作为一种重要的知识管理工具&#xff0c;对于提高团队协作效率、促进知识共享与创新具有不可替代的价值。接下来就说一下知识库在跨地域团队协作中的重要性及…

JVM简单学习

jvm与字节码 jvm只需关注字节码文件 jvm由哪些部分构成 1.类加载子系统&#xff0c;将磁盘中的字节码文件加载到方法区的内存空间中 类加载器分两种&#xff1a;引导类加载器是jvm底层中用C和C语言写的 各个默认的类加载器的不同区别在于 各自默认负责要加载的类的目录不一…

web前端游戏项目-辨色大比拼【附源码】

web前端游戏项目-辨色大比拼【附源码】 《辨色大比拼》是一个旨在测试和提升玩家颜色识别能力的在线游戏。在游戏中&#xff0c;玩家将通过辨识颜色来解谜并推进游戏进程。辨色大比拼也是一个寓教于乐的游戏&#xff0c;它不仅提供了一个有趣的辨色挑战&#xff0c;还能帮助玩…

通过 Higress Wasm 插件 3 倍性能实现 Spring-cloud-gateway 功能

作者&#xff1a;韦鑫&#xff0c;Higress Committer&#xff0c;来自南京航空航天大学分布式系统实验室 导读&#xff1a;本文将和大家一同回顾 Spring Cloud Gateway 是如何满足 HTTP 请求/响应转换需求场景的&#xff0c;并为大家介绍在这种场景下使用 Higress 云原生网关的…

【Linux】Linux常见指令解析上

目录 1. 前言2. ls指令3. pwd指令4. cd指令3.1 cd常见快捷指令 4. touch指令5. mkdir指令6. rmdir指令 && rm指令 &#xff08;重要&#xff09;6.1 rmdir指令6.2 rm指令 7. man指令 1. 前言 这篇文章我们将详细介绍一下Linux下常见的基本指令。 2. ls指令 语法: ls [选…

掌握函数式组件:迈向现代化前端开发的关键步骤(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

精通推荐算法1:为什么需要推荐系统(系列文章,建议收藏)

作者简介&#xff1a; 腾讯算法研究员。硕士毕业于中国科学院大学。在阿里和腾讯工作多年&#xff0c;拥有丰富的搜索和推荐算法经验。CSDN博客专家&#xff0c;原创文章100篇。发表专利15个&#xff0c;其中已授权6个。 1 概述 随着互联网的大力发展&#xff0c;用户规模和…

操作无法完成(错误 0x000006ba),Windows 11 PDF打印机无法使用解决办法

操作无法完成(错误 0x000006ba)&#xff0c;Windows 11 PDF打印机无法使用解决办法 解决方式一 先重启一次电脑&#xff0c;看看是否可以解决问题。 解决方式二 重新启动 Printer Spooler 服务

降本后如何有效增效

在当今竞争激烈的商业环境中&#xff0c;“勒紧裤腰带”式的求生存谋发展&#xff0c;已成为更多成长型企业常态化的战略方向之一了。然而&#xff0c;如何在有限的资源成本下释放更多的效能&#xff1f;降本策略是否会影响组织活力造成得不偿失的结果&#xff1f;如果降本之后…

Maya python清除命名空间

问题描述&#xff1a; Maya命名空间可能存在嵌套。 如上&#xff0c;直接删除 :female_actor02会出现异常。 因此需要先删除子命名空间&#xff0c;再删除父命名空间。 解决方法&#xff1a; def remove_namespace_node(namespace_name, ns_parent":"):""…

解决虚拟机卡顿、卡死、待机后不动的情况(真实有效

本人环境&#xff1a; VM workstation 17.5 ubuntu 22.04 虚拟机配置&#xff1a;4核 4g issue&#xff1a; 出现开机卡死不动运行一段时间&#xff0c;可能半小时不到&#xff0c;就页面卡死不动经常需要关机重启才解决&#xff0c;可能没有解决 1.配置虚拟化引擎 这一步我称…

旅游品牌网站搭建的作用是什么

我国旅游业规模非常高&#xff0c;各地大小旅游景区也是非常多&#xff0c;尤其节假日更是可以达到峰值&#xff0c;无论周边游还是外地游对所要去的景区&#xff0c;消费者总是需要来回了解很多&#xff0c;浏览器查或旅行社咨询等。 对旅游企业而言&#xff0c;传统线下方式…

css 实现满屏升空的气球动画

最终实现效果 demo放在最后了。。。。 问题一 怎么实现满屏气球&#xff1f;简单理解就是多个气球的合并&#xff0c;难道要写多个盒子吗&#xff1f;确实是这样子&#xff0c;但可以有更好的办法&#xff0c;其实就是通过原生操作多个盒子生成&#xff0c;所以只需要实现一个…

【JavaWeb学习笔记】13 - JSP浏览器渲染技术

项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/jsp 目录 项目代码 JSP 一、JSP引入 1.JSP现状 2.为什么需要JSP 二、JSP基本原理及使用 1.基本介绍 2.快速入门 ​编辑 3.JSP运行原理 4.page指令 三、JSP三种常用的脚本 1.声明脚本基本语…

做到这两条,破解35岁中年危机

最近我在看吴军老师的《富足》这本书&#xff0c;其中有一篇文章讲的是如何破解35岁中年危机&#xff0c;我觉得讲清楚了这个问题的本质&#xff0c;我在这里分享给你&#xff0c;以下内容大部分摘抄自《破解35岁中年危机》一章。 35岁中年危机的原因 35岁中年危机的说法好像…

nodejs微信小程序+python+PHP计算机网络在线考试系统-计算机毕业设计推荐

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

04_线性表

线性表 顺序表顺序表的实现顺序表的遍历顺序表的容量可变顺序表的时间复杂度java中ArrayList实现 链表单向链表单向链表API设计java中LinkedList实现 链表的复杂度分析链表反转快慢指针中间值问题单向链表是否有环问题有环链表入口问题 循环链表约瑟夫问题 栈栈概述生活中的栈计…