Linux信号捕捉

要处理信号, 我们进程就得知道自己是否收到了信号, 收到了哪些信号, 所以进程需要再合适的时候去查一查自己的pending位图 block 位图 和 hander表, 什么时候进行检测呢?

当我们的进程从内核态返回到用户态的时候, 进行信号的检测和处理。

我们就先简单的解释一下嘛, 内核态最常见的时候就是我们在使用系统调用的时候, 此时不仅仅我们要去执行系统调用里的代码, 我们还得有资格去访问操作系统内的资源, 所以此时操作系统会自动将我们的身份变化为内核身份, 这就是我们的内核态, 而用户态就是我们在执行我们自己编写的代码的时候的状态。

为什么要选择内核态返回到用户态的时候进行信号的检测呢?
因为可以保证此时进程一定没有在做重要的事情, 所以顺路就检测一下信号。

内核是如何实现信号捕捉的?

在这里插入图片描述

sigaction

在这里插入图片描述

接下来我们看看struct sigaction的结构

在这里插入图片描述
由于我们现在只关心普通信号, 所以我们只需要了解其中的第一个字段和第三个字段这两个字段就可以了。
其中 第一个其实就是一个函数指针, 他指向的就是处理这个信号的hander方法。

如果想快速的使用这个接口, 我们只需要使用第一个参数即可

在这里插入图片描述
在这里插入图片描述

问题1 pending位图是什么时候被处理的?

我们知道在处理完信号后pending位图会将信号对应的位置从1 -> 0, 但是, 具体是在什么时候变更的呢?

我们在handler方法的开头打印一下pending位图, 看看对于信号的位置是否为0, 如果为0那么就代表调用handler前pending就已经被处理了, 否则就是在调用玩handler后pending才被处理的。

在这里插入图片描述
在这里插入图片描述
可以发现2号位为0

所以就可以得出结论, 在调用handler前, 操作系统就已经将pending位图处理过了。

在这里插入图片描述

问题2 为什么在调用handler的时候要将对应的信号屏蔽呢?

因为如果我们hanlder里有系统调用, 那么就会存在内核态向用户态的变化, 就又会去检测信号, 可能会导致信号被嵌套调用

可重入函数

在这里插入图片描述
假如我们在执行链表的头插, 刚执行完p->next = head进程就切走了, 切回来后我们会先进行信号的检测, 如果此时检测到一个信号然后去执行他的处理方法, 恰好他也要往链表头插, 那么这个函数有在handler中被进入了, 我们把这种现象称为函数的重复进入 简称 函数被重入了, 也就是main执行流还没执行完呢, handler执行流又去执行这个函数了。

最后就会变成这种情况

在这里插入图片描述

最后node2节点就丢失了, 这样就出了问题。

如果一个函数在被重复进入的情况下, 可能会出错, 我们称这种函数为不可重入函数否则称为可重入函数

显然, 我们刚刚的那个insert就是不可重入函数。
注意: 可重入 或 不可重入 都不是褒义 或者 贬义, 他们只是描述现象。
目前我们所学到的大部分函数都是不可重入函数。

volatile关键字

在这里插入图片描述

在这里插入图片描述
我们不加优化编译运行, 发现按下Ctrl+ c后代码正常退出
在这里插入图片描述
而当我们加上优化后再运行
在这里插入图片描述
此时就发现退不了了。

由于不同的编译器处理策略不一样, 所以并不是所有的编译器都会发这个flag优化进CPU内寄存器的。

为什么这次没有退出呢?

我们可以看到, 当我们在按下ctrl + c 的时候, 打印出了catch 2 的消息, 说明此时flag应该是被置为1了的, 可是奇怪的是, 为什么进程没有退出呢?

正常情况下在执行!flag的时候, 是CPU先将flag从内存中读取到寄存器里, 然后再对flag执行逻辑运算, 而在优化后, 他发现了flag在内存中不会做修改, 那么他就不再去内存里拿flag了, 而是放在寄存器里直接用。

为了防止编译器的这种过分优化 我们可以使用volatile关键字来修饰这个flag
在这里插入图片描述
在这里插入图片描述
此时我们就发现, 按下ctrl + c后我们进程还是可以正常退出的。

volatile关键字的作用就是 防止编译器过度优化, 保持内存的可见性。

SIGCHLD信号(17号信号) - 了解即可

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
所以我们父进程在等待子进程的时候, 可以根据信号进行异步等待
在这里插入图片描述

但是我们还是必须得保证父进程不能再子进程之前退出!

上诉的代码还是有问题的, 因为父进程的子进程可能有很多个, 如果他们同时退出的话就只能成功的回收其中的一个了。

在这里插入图片描述

事实上, 由于Unix 的历史原因(Linux是仿Unix的), 想要不产生僵尸进程还有一种办法就是在父进程中将SIGCHLD的处理动作设为SIG_IGN, 这样的话fork出来的子进程将会在终止后自动被清除, 不会产生僵尸进程, 也不会通知父进程。
(系统默认的忽略动作通常与用户设置的SIG_IGN是一样的, 但是在这里是一个特例)

在官方手册里, 17号新号的默认动作其实不是SIG_IGN 而是 SIG_DFL, 只是SIG_DFL的动作是IGN也就是什么都不做。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Springboot的教学辅助系统(有报告)。Javaee项目,springboot项目。

演示视频: 基于Springboot的教学辅助系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&…

【Linux】Linux线程

一、Linux线程的概念 1.什么是线程 1.一个进程的一个执行线路叫做线程,线程的一个进程内部的控制序列。 2.一个进程至少有一个执行线程 3.线程在进程内部,本质是在进程地址空间内运行 4.操作系统将进程虚拟地址空间的资源分配给每个执行流&#xff0…

上位机图像处理和嵌入式模块部署(树莓派4b代码优化)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 我们把程序从pc端port到嵌入式开发板上面,好处是降低了部署成本,代价是牺牲了设备性能。所以等到程序真正在开发板子上面运…

YARN详解

YARN 简介 YARN 是Yet Another Resource Negotiator的缩写。 YARN是第二代MapReduce,即MRv2,是在第一代MapReduce基础上演变而来的,主要是为了解决原始Hadoop扩展性较差,不支持多计算框架而提出的;通俗讲就是资源管理器. YARN核心思想: 将 MR1 中资源管理和作业调度两个功能分…

Linux\_c输出

第一条Linux_c输出 初界面 : ls # 显示目录下的文件cd # 进入到某个目录 # 比如 我进入了Codels # 发现没有显示, 说明为文件下为空vim cpucdoe.c # 创建一个 .c的源码文件进入到了vim的编辑界面: i # 按i 就可以进行编辑 , 下面显示插入标识在编辑模式下, 可以通…

QX-mini51学习---(2)点亮LED

目录 1什么是ed 2led工作参数 3本节相关原理图分析 4本节相关c 5实践 1什么是ed 半导体发光二极管,将电能转化为光能,耗电低,寿命长,抗震动 长正短负,贴片是绿点处是负极 2led工作参数 3本节相关原理图分析 当…

(五)JVM实战——JVM性能调优与监控

JVM调优案例的场景 为什么要调优:防止或者解决jvm虚拟机中的OOM问题;减少FullGC出现的频率,解决系统运行卡、慢问题JVM调优案例的四个方面 OOM(堆溢出):java heap spaceOOM(元空间溢出):MetaspaceOOM(GC overhead lim…

cmake install命令无法覆盖同名文件

文章目录 1. 问题记录2. 原因排查3. 解决方案 1. 问题记录 我有两个同名文件test.txt,它们内容不同,但时间戳相同(文件属性中的修改时间相同) 我希望在cmake中利用install命令,将${PATH_SRC}/test.txt替换${PATH_DES…

idea修改maven项目名称及子模块名称

一、修改目录名称 shift F6修改目录,选择“rename module and dictionary”。![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/43efd9c6af6e43ad9656455db94b37a2.png)二、修改子项目pom的 三、修改父项目pom的 四、刷新maven项目

Redis教程——主从复制

在上篇文章我们学习了Redis教程——管道,这篇文章学习Redis教程——主从复制。 主从复制 为了数据更加安全可靠,在实际的项目中,肯定是有多个Redis服务,主机Redis以写为主,从机Redis以读为主,当主机Redis…

JavaScript异步编程——03-Ajax传输json和XML

Ajax 传输 JSON JSON 的语法 JSON(JavaScript Object Notation):是 ECMAScript 的子集。作用是进行数据的交换。语法更为简洁,网络传输、机器解析都更为迅速。 语法规则: 数据在键值对中 数据由逗号分隔 花括号保存对象 方括号保存数组…

Python批量计算多张遥感影像的NDVI

本文介绍基于Python中的gdal模块,批量基于大量多波段遥感影像文件,计算其每1景图像各自的NDVI数值,并将多景结果依次保存为栅格文件的方法。 如下图所示,现在有大量.tif格式的遥感影像文件,其中均含有红光波段与近红外…