【Linux】:信号(三)捕捉

信号捕捉

  • 一.sigaction
    • 1.基本使用
    • 2.sa_mask字段
  • 二.可重入函数
  • 三.volatile
  • 四.SIGCHLD信号

承接上文

在这里插入图片描述

果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号。由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 用户程序注册了SIGQUIT信号的处理函数sighandler。 当前正在执行main函数,这时发生中断或异常切换到内核态。在中断处理完毕后要返回用户态的main函数之前检查到有信号SIGQUIT递达。内核决定返回用户态后不是恢复main函数的上下文继续执行,而是执行sighandler函数,sighandler和main函数使用不同的堆栈空间,它们之间不存在调用和被调用的关系,是 两个独立的控流程。sighandler函数返回后自动执行特殊的系统调用sigreturn再次进入内核态。 如果没有新的信号要递达,这次再返回用户态就是恢复main函数的上下文继续执行了。

一.sigaction

1.基本使用

前面已经聊过signal函数了,这里就不再赘述。

+

在这里插入图片描述

第一个参数是传入的信号种类。

第二个和第三个参数都是struct sigaction类型结构体,前面一个是输入型参数,代表你要执行的动作;后一个是输出型参数,会把原本的信息带出,方便之后恢复。

返回值:成功返回0,失败返回-1.

例子

在这里插入图片描述

在这里插入图片描述

前面我们说过信号在发送后,操作系统会把pending位图的该信号位置置1,当处理该信号时将位图置零,然后执行方法。那么究竟是先置零再执行方法,还是方法执行完成后再置零呢?

在handler方法里打印pending图,即可看出先后顺序

在这里插入图片描述

在这里插入图片描述

从结果看出,操作系统是先将pending位图置零,再调用方法。

2.sa_mask字段

当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。 如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。sa_flags字段包含一些选项,本章的代码都把sa_flags设为0,sa_sigaction是实时信号的处理函数。

总之就是防止信号进行嵌套调用。

对比实验,一般情况下如果我们一直发2号信号,那么在处理2号信号时,其他2号信号一直会阻塞,pending图对应位置为1

在这里插入图片描述

在这里插入图片描述

在调用2号信号时同时屏蔽3号信号

在这里插入图片描述

在这里插入图片描述

二.可重入函数

例子:链表头插

在这里插入图片描述

一个链表进行头插时(不带哨兵节点)分为两步,先是p->next=head,接着是head=p。那么当代码执行到第一步时,突然接收到信号,而跑去进行信号中断了(这里并没有调用系统函数为什么能够实现内核态和用户态的转变从而进行信号中断呢?因为操作系统同时会执行多个进程,而为了让这些进程同时都被执行,操作系统会来回切换这些进程,从而不断的进行用户态和内核态的转变)。正巧我们对该信号的捕捉方法也是使用insert进行头插,那么程序就会再让另一个节点指向head。接着信号处理完毕,再返回继续执行第二步head->p。对于这种一个函数被重复调用的情况被称为函数重入。

以上就出现了问题,虽然node1节点插入成功了,但我们丢失了node2节点,从而导致了内存泄漏。

如果一个函数,被重复进入的情况下可能出错,那么就被叫做不可重入函数。否则就被叫做可重入函数。(目前的大部分函数都是不可重入的)

三.volatile

核心作用:防止编译器过度优化,保存内存可见性。

一个例子

在这里插入图片描述

在这里插入图片描述

这里的原理很简单,发送2信号后改变flag的值就不再死循环,但由于我们并未对flagj进行其他使用,如果我们启用编译器的优化功能会发生不同的现象。

在这里插入图片描述

常见的优化是O0~O3,这里使用O1优化。

在这里插入图片描述

在这里插入图片描述

可以看到我们发送了信号2后程序也并没有结束循环。这是为什么呢?

在这里插入图片描述

为了防止出现变量的过度优化,我们就可以使用volatile。

在这里插入图片描述

在这里插入图片描述

四.SIGCHLD信号

进程一章讲过用wait和waitpid函数清理僵尸进程,父进程可以阻塞等待子进程结束,也可以非阻塞地查询是否有子进程结束等待清理(也就是轮询的方式)。采用第一种方式,父进程阻塞了就不能处理自己的工作了;采用第二种方式,父进程在处理自己的工作的同时还要记得时不时地轮询一下,程序实现复杂。

其实,子进程在终止时会给父进程发SIGCHLD信号,该信号的默认处理动作是忽略,父进程可以自定义SIGCHLD信号的处理函数,这样父进程只需专心处理自己的工作,不必关心子进程了,子进程 终止时会通知父进程,父进程在信号处理函数中调用wait清理子进程即可。

在这里插入图片描述

验证

在这里插入图片描述

在这里插入图片描述

所以在进行进程等待时,我们可以采用基于信号的方式等待。

在这里插入图片描述

事实上,由于UNIX 的历史原因,要想不产生僵尸进程还有另外一种办法:父进程调 用sigaction将SIGCHLD的处理动作置为SIG_IGN,这样fork出来的子进程在终止时会自动清理掉,不会产生僵尸进程,也不会通知父进程。系统默认的忽略动作和用户用sigaction函数自定义的忽略 通常是没有区别的,但这是一个特例。此方法对于Linux可用,但不保证在其它UNIX系统上都可用。

在这里插入图片描述

平常我们创建子进程后并没有主动释放但也并没有影响,因为Linux默认把17号信号设置成了SIG_IGN。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React Native环境搭建及Hello World

写这篇博客的目的就是想说,react native 挺简单,但是大部分初级前端会被环境搭建给难住,从而放弃. 环境搭建 环境搭建其实说简单也挺简单的,有经验的前端直接翻看react native中文文档就行,直接按上面来肯定没错 以下以安卓开发,windows配置环境为例,来演示一遍 首先 电脑…

【开发PaaS】基于Postgresql的开发平台Supabase

Supadase是开源的。我们选择可扩展的开源工具,使其易于使用。 Supadase不是Firebase的1对1映射。虽然我们正在构建Firebase提供的许多功能,但我们不会以同样的方式进行: 我们的技术选择大不相同;我们使用的一切都是开源的&#…

python高级练习题库实验1(B)部分

文章目录 题目1代码实验结果题目2代码实验结果题目3代码实验结果题目4代码实验结果题目5代码实验结果题目总结题目1 打包糖果小游戏,用户输入糖果品牌与个数,还有一个盒子里面可以装多少个糖果,输出一些打印信息,如下图所示: 代码 print("Packaging lollies into…

Python+requests+Jenkins接口自动化测试实例

在做功能测试的基础上,我平时也会用postman测试接口,不过postman只能测试一个一个接口,不能连贯起来,特别是我们公司的接口很多都是要用到token的,导致我每次测个需要登录的接口都要去获取到token,做了很多…

Git常用命令#更改用户名

1.查看当前用户信息 git config user.name2.更改用户名 特定仓库中更改用户名 如果你只想在特定仓库中更改用户名,可以在不使用 --global 参数的情况下执行相同的命令,并进入特定仓库的目录进行修改。 cd /path/to/your/repository git config user.na…

ipa应用测试平台怎么开开具发票

控制台-个人中心-发票管理 ●点击申请发票可以开具发票 ●申请发票-填写资料-勾选订单 ●个人发票开具以及公司发票开具 ●提交发票申请 ●等待申请成功开具发票 ●发票开具成功,我们可以开具或者查看发票

《曾国藩传》:崇尚笨拙的人生哲学

哈喽啊,大家好,我是雷工! 以前读书喜欢读小说,喜欢看《我从你的全世界路过》《云间有个小卖铺》这些轻松的小说,读起来很轻松。 随着年龄增长,阅历的增加开始喜欢读历史,读人物传记,…

MOS管的静电击穿问题

MOS管输入电阻很高,为什么一遇到静电就不行了? 静电击穿:由于静电的积累导致电压超过了原本MOS的绝缘能力,导致电流突然增大的现象。 MOS管基础知识了解: G极(gate)—栅极,不用说比较好认 S极(source)—源…

C#中GDI+绘图应用(柱形图、折线图和饼形图)

目录 一、柱形图 1.示例源码 2.生成效果 二、折线图 1.示例源码 2.生成效果 三、饼形图 1.示例源码 2.生成效果 GDI绘制的一些常用的图形,其中包括柱形图、折线图和饼形图。 一、柱形图 柱形图也称为条形图,是程序开发中比较常用的一种图表技术…

【STM32】EXTI外部中断

1 中断系统 1.1 中断简介 中断:在主程序运行过程中,出现了特定的中断触发条件(中断源),使得CPU暂停当前正在运行的程序,转而去处理中断程序,处理完成后又返回原来被暂停的位置继续运行。 比如&a…

Unittest单元测试框架之unittest_执行用例的详细信息

unittest_执行用例的详细信息 用unittest.main()执行测试集 这里的verbosity是一个选项,表示测试结果的信息复杂度,有三个值: 0 (静默模式): 你只能获得总的测试用例数和总的结果 比如 总共100个 失败20 成功801 (默认模式): 非常类似静默模式 只是在…

SRE-架构框架-可靠性

Google-架构框架-可靠性 可靠性概览 Google Cloud 架构框架中的此类别介绍如何在云平台上构建和运营可靠的服务。此外,您还将了解一些支持可靠性的 Google Cloud 产品和功能。 该架构框架介绍了最佳实践,提供了实现建议,并说明了一些可用的…

LeetCode Hot100 75.颜色分类

题目: 给定一个包含红色、白色和蓝色、共 n 个元素的数组 nums ,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。 必须在不使用库内置的 so…

数据结构——图解链表OJ题目

学完了单链表之后,我们对其基本结构已经有了一定的了解,接下来我们通过一些题目强化对链表的理解,同时学习一些面试笔试题目的新思路以及加强对数据结构单链表的掌握。 目录 题目一.876. 链表的中间结点 - 力扣(LeetCode&#x…

微服务学习|DSL查询语法、搜索结果处理、RestClient查询文档、黑马旅游案例

DSL查询语法 DSLQuery的分类 Elasticsearch提供了基于JSON的DSL (Domain Specific Language) 来定义查询。常见的查询类型包括: 查询所有:查询出所有数据,一般测试用。例如:match_all 全文检索 (full text)查询: 利用分词器对用户输入内容分词,然后去…

在QTableView中使用各种自定义委托

QT的MVC(View/Delegate)模型十分强大,可以利用各种控件来对表格的输入进行限制,不过我以前一直没有过,这几天研究了一下,写个小例子,希望大家喜欢。 如果看不懂这个例子,请先看QT的自…

带删除的并查集

Almost Union-Find 支持三种操作 合并 x x x和 y y y所在的集合把 x x x移到 y y y所在的集合求 x x x所在的集合的元素个数和元素之和 操作1和3是基本的并查集的操作. 关键在于操作 2 2 2: 若使用朴素的并查集,把节点 1 1 1合并到 3 3 3所在的集合,会…

List系列集合

List系列集合特点:有序,可重复,有索引 ArrayList:有序,可重复,有索引 LinkedList:有序,可重复,有索引 (底层实现不同!适合的场景不同!…

TZOJ 1402 Bitset

答案&#xff1a; #include <stdio.h> int main() {int n 0, j 0; while (scanf("%d", &n) ! EOF && (n>0 && n<1000)) //多组输入{int arr[32], i 0;while (n > 0) {arr[i] n % 2; //除2取余法n / 2;}for (j i -…

接口自动化测试思路和实战之模块化测试脚本框架

模块化测试脚本框架 需要创建独立的可描述的模块、程序片断以及待测试应用程序的脚本。这些小脚本进行组合&#xff0c;就能组成用来独立运行特定的测试的测试用例脚本。 场景一: 开发把 access_token接口地址由/cgi-bin/token 改为/cgi-bin/get_token或者修改参数等 》开发把…