Linux进程信号 | 信号保存

news2024/11/23 22:06:57

阻塞信号

信号其他相关常见概念

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

在内核中的表示

信号的三种概念在操作系统中的表示,在进程的PCB中,操作系统会为我们维护3张表,分别为pending表、block表、handler表。

pending表:位图结构。比特位的位置表示哪一个信号,比特位的内容代表是否收到信号。 

block表:位图结构。比特位的位置表示哪一个信号,比特位的内容代表是否对应的信号该被阻塞。

handler表:函数指针数组。对应的函数指针就是 void (*sighander_t)(int) 类型。该数组的下标表示信号的编号,数组特定下标的内容表示该信号的递达动作。

下面我们来举一个小例子来看一下信号的默认处理动作和忽略动作:

int main()
{
    signal(2, SIG_IGN);
    while (true)
    {
        sleep(1);
    }
    return 0;
}

可以看到当我们将信号的默认处理动作设置为忽略时,进程对ctrl-c就没有了反应。

从定义中来查看就是与我们设置的自定义动作相类似:

将数字强制转换成了函数指针类型。

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

sigset_t

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

简要来说,就是我们可以通过sigset_t的对象来控制penging和block这两个位图结构。

信号集操作函数

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

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在该信号集中添加或删除某种有效信号。

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

sigpromask

调用函数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返回前,至少将其中一个信号递达。

sigpending

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

下面展示一个sigpending的小例子可以用来获取被pending的信号,我们将使用函数将2号信号屏蔽,当过去一定的时间之后再让信号的屏蔽恢复,并通过自定义的行为来判断。

static void PrintPending(const sigset_t &pending) {
    cout << "当期进程的pending信号集:";
    for (int signo = 1; signo <= 31; ++signo) {
        if (sigismember(&pending, signo)) cout << "1";
        else cout << "0";
    }
    cout << endl;
}

static void handler(int signo) {// 添加了static之后该函数只能在本文件中使用
    cout << "对特定信号:" << signo << "执行捕捉动作" << endl;
}

int main() {
    // 1. 屏蔽2号信号
    sigset_t set, oset;
    // 1.1 初始化
    sigemptyset(&set);
    sigemptyset(&oset);
    // 1.2 将2号信号添加到set中
    sigaddset(&set, SIGINT);
    sigaddset(&set, 3);
    // 1.3 将新的信号屏蔽字设置进程
    sigprocmask(SIG_BLOCK, &set, &oset);
    signal(2, handler);
    // 2. while获取进程的pengding信号集,并01打印
    int cnt = 0;
    while (true) {
        // 2.1 获取pending信号集
        sigset_t pending;
        sigemptyset(&pending);
        int n = sigpending(&pending);
        assert(n == 0);
        (void)n; // 保证不会出现编译时warning
        // 2.2 打印
        PrintPending(pending);
        // 休眠
        sleep(1);
        // 10秒之后恢复对所有信号的block动作
        if (cnt++ == 10)  {
            cout << "解除对2号信号的屏蔽" << endl;
            sigprocmask(SIG_SETMASK, &oset, nullptr);
        }
    }
}

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

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

相关文章

A Survey of Large Language Models

本文是LLM系列的第一篇文章&#xff0c;针对《A Survey of Large Language Models》的翻译。 大语言模型综述 摘要1 引言2 概述2.1 LLM的背景2.2 GPT系列模型 的技术演化 3 LLMs的资源3.1 公开可用的模型检查点或APIs3.2 常用的语料库3.3 库资源 4 预训练4.1 数据收集4.1.1 数…

图的企业应用-A*算法自动寻路

引言 MC想必大家都玩过,但鸡哥利用A*自动寻路算法来找箱子 箱子里有鸡你太美唱片&#xff0c;和准备好的篮球 当然在这是游戏中找到的宝箱 还得原石x5等一大堆的养成物品 ???等等 ,原神 玩家露出鸡脚了吧! 不应该是 有鸡你太美唱片,还有一条鱼并且给梅里猫的名叫荔枝的? 这…

【MyBatis学习】Spring Boot(SSM)单元测试,不用打包就可以测试我们的项目了,判断程序是否满足需求变得如此简单 ? ? ?

前言: 大家好,我是良辰丫,在上一篇文章中我们学习了MyBatis简单的查询操作,今天来介绍一下Spring Boot(SSM)的一种单元测试,有人可能会感到疑惑,框架里面还有这玩意?什么东东呀,框架里面是没有这的,但是我们简单的学习一下单元测试,可以帮助我们自己测试代码,学习单元测试可以…

SEO留痕霸屏技术原理实现分析

留痕效果 通常是查询某个关键词&#xff0c;出现大量搜索结果网页霸屏&#xff0c;而且都会引导到其他平台或者网站进行浏览和查看。留痕网站和指向网站或平台无关联。 示例图片&#xff1a; 原理分析 首先通过内容和链接很容易明白&#xff0c;本质上就是一个搜索页面&…

OpenAI API升级:新GPT-3.5 Turbo和GPT-4助力AIGC应用大放异彩

theme: orange 前言 北京时间2023年6月13日&#xff0c;OpenAI宣布对其领先的生成型AI模型GPT-3.5 Turbo和GPT-4进行一系列更新&#xff0c;以提高工作场所的人工智能能力。这些改进包括引入全新的函数调用功能、增强的可引导性、GPT-3.5 Turbo的扩展上下文&#xff0c;以及修订…

数值分析第九章节 用Python实现常微分方程初值问题的数值解法

参考书籍&#xff1a;数值分析 第五版 李庆杨 王能超 易大义编 第9章 常微分方程初值问题的数值解法 文章声明&#xff1a;如有发现错误&#xff0c;欢迎批评指正 文章目录 欧拉法后退的欧拉方法梯形方法改进欧拉公式补充龙格—库塔方法线性多步法阿当姆斯显示与隐式公式 9.1引…

5.3.3 因特网的路由协议(三)OSPF协议

5.3.3 因特网的路由协议&#xff08;三&#xff09;OSPF协议 前面我们学习了基于距离向量算法的路由信息协议RIP&#xff08;5.3.2 因特网的路由协议&#xff08;二&#xff09;基于距离向量算法的RIP协议&#xff09;,为了克服RIP协议的局限性于是就有了新的内部网关协议OSPF…

30行代码实现通用无限列表函数

前言&#xff1a; 前两天接到了一个需求&#xff0c;主要功能是实现类似于 B站 消息页面的那种效果&#xff0c;右侧几个 tab 都需要使用到无限加载的功能。 大家都知道&#xff0c;程序员是很懒的&#xff0c;不可能这几个页面全都写一遍重复的逻辑。所以在接到这个需求的时…

HBuilder连接手机模拟器调试,进行抓包

hbuilder连接手机模拟器 1.adb是什么&#xff1f;引用 2. 进行adb路径设置&#xff0c;选中模拟器中的adb路径&#xff0c;配置好端口&#xff0c;夜神模拟器端口&#xff1a;62001 3.运行到Andriod基座 在HBuilder连接模拟器过程中&#xff0c;对接口进行抓包 1.安装抓包工…

Spring Security --- 自定义Filter

简介任何 Spring Web 应用本质上只是一个 servletSecurity Filter在 HTTP 请求到达你的 Controller 之前过滤每一个传入的 HTTP请求Filter请求过滤器可以帮助进行HttpServletRequest请求和HttpServletResponse响应的过滤在自定义的Filter过滤器中可以对请求进行过滤&#xff0c…

控制并发流程,做好线程间的协调

一、概述 1. 什么是控制并发流程&#xff1f; 线程一般是由线程调度器自动控制的&#xff0c;但有些场景需要按照我们程序员的意愿去实现多线程之间相互配合&#xff0c;从而满足业务逻辑。比如&#xff1a; 让线程A等待线程B执行完后再执行等一些相互合作的逻辑&#xff1b…

【表面缺陷检测】基于yolov5的钢轨表面缺陷检测(附代码和数据集,Windows系统)

写在前面: 首先感谢兄弟们的订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 路虽远,行则将至;事虽难,做则必成。只要有愚公移山的志气、滴水穿石的毅力,脚踏实地,埋头苦干,积跬步以至千里,就…

python打包后报错,无法启动,电脑缺少api-ms-win-core-path-11-1-0.dll

参考&#xff1a;《运行打包python程序时报&#xff1a;无法启动此程序&#xff0c;因为计算机中丢失 api-ms-win-core-path-l1-1-0.dll 尝试重新安装该程序以解决此问题。》 原因&#xff1a;python版本较高&#xff0c;打包时的python版本是python3.10&#xff0c;而运行打包…

mdBook介绍及使用——使用 Markdown 创建你自己的博客和电子书

目录 介绍一、下载与创建项目1.下载2.初始化3.结构说明 二、编写文章与启动1.编写文章2.构建3.启动 mdbook 服务 三、其他配置 介绍 mdBook 是一个使用 Markdown 创建书籍的命令行工具。它非常适合创建产品或 API 文档、教程、课程材料或任何需要清晰、易于导航和可定制的演示…

LED开关电源里的PCB回路设计应该怎么做?

LED开关电源的研发速度在最近几年中有了明显的技术飞跃&#xff0c;新产品更新换代的速度也加快了许多。作为最后一个设计环节&#xff0c;PCB的设计也显得尤为重要&#xff0c;因为一旦在这一环节出现问题&#xff0c;那么很可能会对整个的LED开关电源系统产生较多的电磁干扰&…

界面控件DevExtreme UI组件——增强的自定义功能

在本文中&#xff0c;我们将回顾DevExtreme UI组件在v22.2版本主要更新中一系列与自定义相关的增强。 DevExtreme拥有高性能的HTML5 / JavaScript小部件集合&#xff0c;使您可以利用现代Web开发堆栈&#xff08;包括React&#xff0c;Angular&#xff0c;ASP.NET Core&#x…

6、微服务组件openfeign

1、在消费端的项目中引入openfeign依赖 首先需要确保引入了springcloud&#xff0c;因为openfeign依赖与springcloud 在消费端的pom.xml中引入openfeign&#xff0c;父项目中已经引入了springcloud了 <?xml version"1.0" encoding"UTF-8"?> <…

行云创新CloudOS助力蜂巢能源获中国信通院2023云原生应用优秀案例奖

2023 年 6 月 6 日&#xff0c;工业和信息化部主办的ICT 中国高层论坛-云原生产业高峰论坛成功举办&#xff0c;活动期间&#xff0c;中国信通院发布了“2023云原生应用优秀案例奖”获奖名单。其中&#xff0c;蜂巢能源作为中国新能源行业的代表之一&#xff0c;凭借其基于行云…

IKEA EDI项目开源介绍

近期为了帮助广大用户更好地使用 EDI 系统&#xff0c;我们根据以往的项目实施经验&#xff0c;将成熟的 EDI 项目进行开源。用户安装好知行之桥EDI系统之后&#xff0c;只需要下载我们整理好的示例代码&#xff0c;并放置在知行之桥指定的工作区中&#xff0c;即可开始使用。 …

一次 Nacos 导致的 CPU 飙高问题完整复盘

今天下午突然 出现 测试环境 cpu飙高&#xff0c;干到了 60%&#xff0c;其他项目 响应时间明显变长。。。有点吓人&#xff0c;不想背锅 项目背景 出问题的项目是 需要连接各个不同nacos 和不同的 namespace 进行对应操作的 一个项目&#xff0c;对nacos的操作都是httpClien…