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.rhkb.cn/news/321129.html

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

相关文章

微搭低代码入门06分页查询

目录 1 创建自定义代码2 编写分页代码3 创建页面4 创建变量5 配置数据列表总结 我们在数据模型章节介绍了微搭后端服务编写的三种方式,包括Http请求、自定义代码、云函数。本篇我们详细讲解一下利用自定义代码开发分页查询的功能。 1 创建自定义代码 打开控制台&am…

绘唐ai工具怎么获取

这款产品的最大亮点在于其高度精准的语音克隆能力,利用先进的模型,能够捕捉到用户独特的音调、音高和调制方式,使用户能够以前所未有的方式复制和利用自己的声音。仅需10秒钟的录制时间,即可实现声音的克隆,相当便捷。…

基于FPGA的数字密码锁电路Verilog代码Quartus仿真

名称:基于FPGA的数字密码锁电路Verilog代码Quartus仿真(文末获取) 软件:Quartus 语言:Verilog 代码功能: 数字密码锁电路的设计 1.设计任务:设计并制作数字密码锁电路 2.设计要求 1.用EDA实训仪的I/设备和PLD志…

上证50etf期权到底该怎么玩?

今天期权懂带你了解上证50etf期权到底该怎么玩?ETF期权是一种股票市场上的金融衍生品,它是在交易所上市交易的期权合约,其标的资产是某个特定的交易所交易基金(ETF),如上证50指数ETF或沪深300指数ETF等。 上…

Docker搭建LNMP+Wordpress

目录 一.项目模拟 1.项目环境 2.服务器环境 3.任务需求 (1)使用 Docker 构建 LNMP 环境并运行 Wordpress 网站平台 (2)限制 Nginx 容器最多使用 500MB 的内存和 1G 的 Swap (3)限制 Mysql 容器写 /d…

期权买方要保证金吗?期权交易保证金怎么计算?

今天期权懂带你了解期权买方要保证金吗?期权交易保证金怎么计算?期权保证金其实就是你在购买期权合约时,作为卖方要付出的那一小笔钱。简单说,就是为了防止你违约,给交易双方一个保障的“小押金”。 期权买方要保证金吗…

渗透测试流程

一、攻击流程 信息收集阶段→漏洞分析阶段→攻击阶段→后渗透阶段 二、信息收集 1、收集内容: IP资源:真实IP获取、旁站信息收集、C段主机信息收集域名发现:子域名信息收集、子域名枚举发现子域名、搜索引擎发现子域名、第三方聚合服务器发…

TCP经典异常问题探讨与解决

作者:kernelxing TCP的经典异常问题无非就是丢包和连接中断,在这里我打算与各位聊一聊TCP的RST到底是什么?现网中的RST问题有哪些模样?我们如何去应对、解决?本文将从RST原理、排查手段、现网痛难点案例三个板块自上而…

sprig 项目启动时报错:MybatisDependsonDatabaseInitializationDetector

问题 使用application.yml启动项目报错: 解决方案 修改pom.xml: 修改这两处的版本

Linux提示:mount: 未知的文件系统类型“ntfs”

mount: 未知的文件系统类型“ntfs” 在Linux系统中,如果遇到“mount: 未知的文件系统类型‘ntfs’”的错误,这通常意味着您的系统没有安装支持NTFS文件系统的软件。为了挂载NTFS文件系统,您需要安装ntfs-3g软件包。以下是如何在不同Linux发行…

28.leetcode---前K个高频单词(Java版)

题目链接: https://leetcode.cn/problems/top-k-frequent-words/description/ 题解: 代码: 测试:

自动化运维管理工具----------Ansible模块详细解读

目录 一、自动化运维工具有哪些? 1.1Chef 1.2puppet 1.3Saltstack 二、Ansible介绍 2.1Ansible简介 2.2Ansible特点 2.3Ansible工作原理及流程 2.3.1内部流程 2.3.2外部流程 三、Ansible部署 3.1环境准备 3.2管理端安装 ansible 3.3Ansible相关文件 …

shell脚本编写-测试同一网段内主机是否在线

除了可以使用ansible自动化运维工具判断主机是否在线以外,还可以通过编写Shell脚本来实现。 1、编写脚本 #! /bin/bash #测试192.168.81.0/24网段中哪些主机处于开机状态,哪些主机处于关机状态# #方法一:使用for循环判断 # for i in {1..25…

golang for经典练习 金字塔打印 示例 支持控制台输入要打印的层数

go语言中最经典的for练习程序 金字塔打印 &#xff0c;这也是其他语言中学习循环和条件算法最为经典的联系题。 其核心算法是如何控制内层循环变量j 每行打印的*号数量 j<i*2-1 和空格数量 j1 || j i*2-1 golang中实现实心金字塔 Solid Pyramid和空心金字塔 Hollow Pyram…

如何根据IP获取国家省份城市名称PHP免费版

最近项目遇到需要根据IP获取用户国家功能需求&#xff0c;网上找了一下&#xff0c;很多API接口都需要付费&#xff0c;考虑为公司节约成本&#xff0c;就取找找有没有开源的 github 上面那个包含多种语言&#xff0c;下面这个只有php&#xff0c;用法很简单 $ip 114.114.114…

华为eNSP中型企业局域网网络规划设计(下)

→b站传送门&#xff0c;感谢大佬← →华为eNSP中型企业局域网网络规划设计&#xff08;上&#xff09;← →拓扑图传送门&#xff0c;可以自己配置着玩← 配置ospf AR3 [AR3]ospf 1 router-id 3.3.3.3 //出口默认路由 [AR3-ospf-1]default-route-advertise always #area…

CVE-2019-19945漏洞复现 Openwrt针对uhttpd漏洞利用

根据官方漏洞的文档&#xff0c;该漏洞的复现工作我会基于openwrt的18.06.4这个版本进行测试。我选取的环境是渗透测试常用的kali-Linux系统&#xff0c;然后在其中搭建docker环境来完成相应的实验环境的部署。我通过这个核心命令获取docker环境&#xff1a; sudo docker impo…

GDPU 天码行空11

&#xff08;一&#xff09;实验目的 1、掌握JAVA中IO中各种类及其构造方法&#xff1b; 2、重点掌握IO中类所具有的IO操作方法&#xff1b; 3、熟悉软件中登录模块的开发方法&#xff1b; 4、掌握IO中读写常用方法。 5、进一步熟悉正则规则的使用方法。 &#xff08;二&…

Git可视化工具tortoisegit 的下载与使用

一、tortoisegit 介绍 TortoiseGit 是一个非常实用的版本控制工具&#xff0c;主要用于与 Git 版本控制系统配合使用。 它的主要特点包括&#xff1a; 图形化界面&#xff1a;提供了直观、方便的操作界面&#xff0c;让用户更易于理解和管理版本控制。与 Windows 资源管理器…

纯血鸿蒙APP实战开发——折叠屏扫描二维码方案

折叠屏扫描二维码方案 介绍 本示例介绍使用自定义界面扫码能力在折叠屏设备中实现折叠态切换适配。自定义界面扫码使用系统能力customScan&#xff0c;其提供相机流的初始化、启动扫码、识别、停止扫码、释放相机流资源等能力。折叠屏折叠状态通过监听display的foldStatusCha…