【Linux】进程信号(下)
目录
一、信号的阻塞
1.1 信号在内核中的保存方式
1.2 sigset_t信号集
(1)信号集操作
(2)sigprocmask函数
(3)sigpending函数
二、信号的处理
2.1 用户态和内核态
2.2 重谈进程地址空间
三、信号的捕捉
sigaction函数
前文:
【Linux】进程信号(上)-CSDN博客文章浏览阅读729次,点赞29次,收藏27次。本篇文章围绕Linux中的进程信号展开讲解,包含信号的概念、信号的产生等内容https://blog.csdn.net/Eristic0618/article/details/142900955
一、信号的阻塞
1.1 信号在内核中的保存方式
前面提到,进程在接收到普通信号时,并不是立即进行处理的
- 信号产生但未被处理的状态称为信号未决(Pending)
- 执行信号的处理动作,称为信号递达(Delivery)
- 信号产生但可以被阻塞(Block)
假设一个信号被阻塞,则这个信号将一直保持未决的状态,直到进程解除对该信号的阻塞才能执行递达动作
进程的阻塞和信号的阻塞是两回事,信号阻塞类似于屏蔽了某个信号
信号的阻塞与忽略也是不同的,信号被阻塞后会一直存在,而忽略是对信号的一种处理动作
进程的PCB中有三个表,分别是block表、pending表和handler表,其中:
- block表是一个位图,又叫做阻塞信号集或信号屏蔽字,记录了某个信号是否被屏蔽,如果对应位置为0表示该信号未被屏蔽,为1则被屏蔽
- pending表也是位图,用于记录进程收到了哪些信号
- handler表是一个函数指针数组,用于记录每种信号的处理方法
三个表一起看,就能知道一个信号是否被屏蔽,是否被收到,处理方法是什么
我们通过signal函数捕捉某个信号,实际上就是把用户提供的函数指针覆盖到handler表的对应位置
信号的处理方式类型为__sighandler_t,实际定义为:
typedef void(*__sighandler_t)(int);
系统中还定义了一些信号的默认处理方法:
#define SIG_DFL ((__sighandler_t) 0)
#define SIG_IGN ((__sighandler_t) 1)
其中SIG_DFL表示收到信号后终止进程,SIG_IGN表示忽略某个信号
1.2 sigset_t信号集
(1)信号集操作
sigset_t是一个数据类型,称为信号集,本质上是一个位图
我们的block表和pending表的类型都是sigset_t,其每一位对应一个信号,值为1或0则表示是否未决或被阻塞
要对一个信号集进行修改,只能通过特定函数:
#include <signal.h>int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset(sigset_t *set, int signum);
int sigdelset(sigset_t *set, int signum);
int sigismember(const sigset_t *set, int signum);
其中:
- sigemptyset函数会将set指向的信号集所有位清零,表示该信号集不包含任何有效信号
- sigfillset函数则会将set指向的信号集每一位置为1
- sigaddset函数会将set指向的信号集中signum号信号对应的位修改为1,表示添加某个信号
- sigdelset函数会将set指向的信号集中signum号信号对应的位修改为0,表示删除某个信号
- sigismember函数会判断signum号信号在set指向的信号集中是否有效,有效返回1,否则返回0,出错返回-1
通过这几个函数,我们就能对一个信号集进行初始化或修改等操作了
(2)sigprocmask函数
#include <signal.h>int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
sigprocmask函数可以读取或修改进程的信号屏蔽字(阻塞信号集),成功返回0,出错返回-1
其中:
- how:更改信号屏蔽字的方式,SIG_BLOCK表示将set中的有效信号添加到当前信号屏蔽字,SIG_UNBLOCK表示将set中的有效信号从当前信号屏蔽字中删除,SIG_SETMASK表示将当前信号屏蔽字设置为set
- set:若为非空,则按照set的内容和how指定的方式对当前信号屏蔽字进行修改
- oset:若为非空,则将当前信号屏蔽字通过该参数读出
若set和oset都为非空,则先读取再修改
(3)sigpending函数
#include <signal.h>int sigpending(sigset_t *set);
sigpending函数可以通过set参数读取当前进程的未决信号集,成功返回0,出错返回-1
例如:
#include <iostream>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>using namespace std;void PrintSigset(sigset_t *set) //打印信号集
{for (int i = 1;i < 32; i++) //遍历所有普通信号{if(sigismember(set, i)) //判断当前信号在信号集中是否有效cout << 1;elsecout << 0;}cout << endl;
}int main()
{sigset_t set, p;sigemptyset(&set);sigaddset(&set, 1); //向信号集中添加1号信号sigprocmask(SIG_BLOCK, &set, NULL); //将set中的有效信号添加到信号屏蔽字中while(true){cout << "process running...,pid: " << getpid() << ", pending: ";sigpending(&p); //取出未决信号集PrintSigset(&p); //打印未决信号集sleep(1);}return 0;
}
运行结果:
在代码中,我们将1号信号添加到了进程的信号屏蔽字中,所以如果进程接收到1号信号后不会对其进行处理
通过运行结果可以发现,在我们向进程发送1号信号后,未决信号集的第一位由0变为1,说明此时1号信号处于未决状态,没有被处理。如果过段时间后再对1号信号解除阻塞,那么进程就会在合适的时候处理信号
当然,和信号的捕捉一样,9和19号信号也是无法被阻塞的。试想一下,如果一个进程将所有的信号都阻塞了,那是不是变得刀枪不入了?
二、信号的处理
2.1 用户态和内核态
我们一直说进程会在合适的时候处理信号,具体是什么时候呢?
进程要知道自己是否收到了信号或是否需要对信号进行处理,就需要访问自己的pending表、block表和handler表。但这三张表都是内核中的数据结构,说明进程一定要处在一种内核状态才能对信号进行处理
首先搞清楚什么是内核态,和与其对应的用户态:
- 用户态(User Mode)是进程运行用户程序的状态,权限较低,只能通过系统调用来请求操作系统提供的服务
- 内核态(Kernel Mode)是操作系统内核的运行状态。进程在调用了系统调用、触发时钟中断或异常后会将CPU的控制权交给操作系统内核并陷入内核态,处于内核态的CPU拥有最高的权限,可以访问操作系统的所有资源
- 为了操作系统的安全,操作系统不允许用户直接对其内部进行操作。但有时用户需要操作系统帮助完成需要更高权限的工作,因此区分了内核态与用户态
这里直接给出结论:我们的进程在从内核态返回到用户态的时候,进行信号的检测与处理
关于进程在用户态和内核态之间的切换,还有一些内容需要我们了解
例如进程在执行一些封装了系统调用的库函数时,就需要从用户态陷入到内核态,其中是通过一条汇编指令 "int 0x80" 实现的
2.2 重谈进程地址空间
Linux的进程地址空间大小为4GB,其中位于较高地址的1GB为内核空间,通过内核级页表映射了操作系统的代码和数据;较低地址的3GB为用户空间,供进程使用,通过用户级页表映射到物理内存中进程自己的代码和数据。
操作系统中有几个进程就有几个用户级页表,但内核级页表在操作系统中只有一份,可以被所有进程看到,所以每个进程的内核空间映射的内容都是一样的
既然内核空间是进程地址空间的一部分,而内核空间又映射了操作系统的代码和数据,那么我们在调用系统调用接口的时候,难道不就是在进程自己的地址空间中调用吗?
站在进程的视角,调用系统调用接口,就相当于我们从用户空间的正文代码中跳转到内核空间,执行完毕后再返回到用户空间
但是操作系统肯定不会允许我们进程随心所欲的访问内核空间的内容,只有进程处于内核态时才拥有访问内核空间的权限。如何判断一个进程是处于用户态还是内核态呢?
- CPU当中存在一个ecs寄存器,若其最低两位比特位为00则代表进程处于内核态,为11则代表进程处于用户态,当执行了int 0x80时就会将这两位从11(用户态)变为00(内核态)。通过检测这两位就可以判断进程处于什么态,是否有权限访问内核空间
既然内核态的权限那么大,那处于内核态的进程能否执行用户空间的代码呢?不行!
依旧是为了操作系统的安全,OS不会执行任何用户所写的代码(避免用户的代码中包含非法操作等情况),因此进程需要从内核态再重新返回用户态执行用户的代码
我们回到信号的话题,看看进程遇到异常收到信号时是如何进行用户态和内核态的切换的
- 当进程发生异常,从用户态陷入到内核态进行异常的处理
- 处理完毕后在返回用户态之前就会检查是否有信号需要处理
- 如果此时对应信号的处理方法是用户自定义的,则需要从内核态返回用户态执行对应函数(如果处理方法是系统默认,则处理完毕后会直接返回代码原来中断的位置继续执行)
- 执行完用户自定义的信号处理方法后,处于用户态的进程无法直接跳转回原来的位置,需要再次陷入内核态
- 处于内核态的进程,能够跳转回主控制流程中上次被中断的地方继续向下执行
三、信号的捕捉
sigaction函数
除了signal函数,我们还可以通过sigaction函数捕捉一个信号(包括实时信号)
#include <signal.h>int sigaction(int signo, const struct sigaction *act, struct sigaction *oact);
sigaction函数用于修改特定信号的处理动作,成功返回0,失败返回-1并设置错误码
其中:
- act和oact是指向sigaction结构体的指针(这个结构体的名字和函数名一样),其结构为
struct sigaction {void (*sa_handler)(int);void (*sa_sigaction)(int, siginfo_t *, void *);sigset_t sa_mask;int sa_flags;void (*sa_restorer)(void);
};
如果要捕捉的是普通信号,我们主要关注结构体中的sa_handler就行,这是我们捕捉信号的自定义处理方法。sa_sigaction是实时信号的处理方法,我们不深入了解
关于sa_mask字段:
在捕捉某个信号时内核会暂时性的将该信号屏蔽,直到将当前信号处理完毕后才会解除屏蔽,避免同样的信号被重复捕捉
如果在处理信号时除了屏蔽当前信号,还希望额外暂时性屏蔽一些其他信号,则通过sa_mask字段进行说明
- 我们自定义的信号处理方法,通过act参数传入,旧的信号处理方法则可以通过oact参数输出
完.
相关文章:
【Linux】进程信号(下)
目录 一、信号的阻塞 1.1 信号在内核中的保存方式 1.2 sigset_t信号集 (1)信号集操作 (2)sigprocmask函数 (3)sigpending函数 二、信号的处理 2.1 用户态和内核态 2.2 重谈进程地址空间 三、信号…...
FlinkCDC 实现 MySQL 数据变更实时同步
文章目录 1、基本介绍2、代码实战2.1、数据源准备2.2、代码实战2.3、数据格式 1、基本介绍 Flink CDC 是 Apache Flink 提供的一个功能强大的组件,用于实时捕获和处理数据库中的数据变更。可以实时地从各种数据库(如MySQL、PostgreSQL、Oracle、MongoDB…...
JavaWeb——Maven(4/8):Maven坐标,idea集成-导入maven项目(两种方式)
目录 Maven坐标 导入Maven项目 第一种方式 第二种方式 Maven坐标 Maven 坐标 是 Maven 当中资源的唯一标识。通过这个坐标,我们就能够唯一定位资源的位置。 Maven 坐标主要用在两个地方。第一个地方:我们可以使用坐标来定义项目。第二个地方&#…...
实现uniapp天地图边界范围覆盖
在uniapp中,难免会遇到使用地图展示的功能,但是百度谷歌这些收费的显然对于大部分开源节流的开发者是不愿意接受的,所以天地图则是最佳选择。 此篇文章,详细的实现地图展示功能,并且可以自定义容器宽高,还可…...
思科网络设备命令
一、交换机巡检命令 接口和流量状态 show interface stats:查看所有接口当前流量。show interface summary:查看所有接口当前状态和流量。show interface status:查看接口状态及可能的错误。show interface | include errors | FastEthernet …...
Egg.js使用ejs快速自动生成resetful风格的CRUD接口
目前的插件能够自动生成egg的crud的都不太好用 我们自己写一个吧 ejs模块 也方便定制 安装依赖 npm install ejs --save ejs 是一个简单易用的模板引擎,常用于 Node.js 应用程序中 在项目根目录下创建 template/controller.ejs 模板文件 use strict;const Co…...
自动化抖音点赞取消脚本批量处理
🌟 前言 欢迎来到我的技术小宇宙!🌌 这里不仅是我记录技术点滴的后花园,也是我分享学习心得和项目经验的乐园。📚 无论你是技术小白还是资深大牛,这里总有一些内容能触动你的好奇心。🔍 &#x…...
基于YOLOv8深度学习的智能车牌检测与识别系统【python源码+Pyqt5界面+数据集+训练代码】目标检测、深度学习实战
背景及意义 智能车牌检测与识别系统通过使用最新的YOLOv8与PaddleOCR算法能够迅速、准确地在多种环境下实现实时车牌的检测和识别。本文基于YOLOv8深度学习框架,通过16770张图片,训练了一个进行车牌检测模型,可以检测蓝牌与绿牌,然后对检测到的车牌使用O…...
qt QGraphicsGridLayout详解
一、概述 QGraphicsGridLayout是Qt框架中用于在QGraphicsScene中布置图形项的一个布局管理器。它类似于QWidget中的QGridLayout,但主要处理的是QGraphicsItem和QGraphicsWidget等图形项。通过合理设置网格位置、伸缩因子和尺寸,可以实现复杂而灵活的布局…...
数字处理系列
(1)将数字转化成中文的过滤器 <template><div><p>数字转中文:{{ 110 | numberToChinese }}</p></div></template><script>export default {filters: {numberToChinese(num) {const chineseNums …...
基于开源Jetlinks物联网平台协议包-MQTT自定义主题数据的编解码
目录 前言 1.下载官方协议包 2.解压 3.自定义主题 4.重写解码方法 5.以下是我解析后接收到的数据 前言 最近这段时间,一直在用开源的Jetlinks物联网平台在学习,偶尔有一次机会接触到物联网设备对接,在协议对接的时候,遇到了…...
【Python】Python2.7升级Python3
需求背景 服务是跑在docker的容器里的,因此要新建image依赖环境是Ubuntu,老的是16.4。 步骤 先准备环境,因为只有你的环境上去了,运行代码的时候才会报错,这样才会把需要改的代码暴露出来。 python3.5目前也是被遗弃的…...
Python 内置函数 round() 详解
在 Python 编程中,round() 函数是一个非常实用的内置函数,用于对数字进行四舍五入。无论是在数据处理、财务计算还是科学计算中,round() 函数都能帮助我们得到所需的精确值。本文将详细介绍 round() 函数的用法和注意事项。 1. round() 函数…...
JavaScript入门中-流程控制语句
本文转载自:https://fangcaicoding.cn/article/52 大家好!我是方才,目前是8人后端研发团队的负责人,拥有6年后端经验&3年团队管理经验,截止目前面试过近200位候选人,主导过单表上10亿、累计上100亿数据…...
kconfig语法(一)
一、安装Kconfiglib python -m pip install windows-curses python -m pip install kconfiglib二、使用样例 ①创建kconfig文件。 ②在kconfig文件添加内容: config KCONFIG_DEMO_ITEM1boolprompt "demonstate item1 for bool learning"config KCONFIG_DEMO_ITE…...
十七、行为型(命令模式)
命令模式(Command Pattern) 概念 命令模式是一种行为型设计模式,它将请求封装成一个对象,从而使您可以使用不同的请求对客户进行参数化,排队请求,以及支持可撤销操作。通过这种模式,调用操作的…...
原材料供应商的GRS认证证书过期了怎么办?
在全球纺织和时尚产业中,GRS(Global Recycle Standard,全球再生标准)认证已成为衡量企业环保和可持续发展的重要指标。然而,当原材料供应商的GRS认证证书过期时,企业需迅速采取行动,以确保供应链…...
C++编程:实现一个基于原始指针的环形缓冲区(RingBuffer)缓存串口数据
文章目录 0. 引言1. 使用示例2. 流程图2.1 追加数据流程2.2 获取空闲块流程2.3 处理特殊字符流程2.4 释放块流程2.5 获取下一个使用块流程 3. 代码详解3.1 Block 结构体3.2 RingBuffer 类3.3 主要方法解析append 方法currentUsed 和 currentUsing 方法release 方法nextUsed 方法…...
LangChain 创始人万字科普:手把手教你设计 Agent 用户交互
LangChain 可以算是 LLM 时代做 AI 应用开发必备的框架和平台,从模型选择、数据库链接与各种 Agent 搭建等,AI 应用的搭建、运行和管理都可以在 LangChain 上进行。 某种意义上,LangChain 可能是最了解 Agent(智能体)…...
Docker 用例:15 种最常见的 Docker 使用方法
容器化应用程序而不是将它们托管在虚拟机上是过去几年一直流行的概念,使容器管理流行起来。Docker 处于这一转变的核心,帮助组织无缝地采用容器化技术。最近,Docker 用例遍布所有行业,无论规模大小和性质如何。 什么是Docker&…...
若依 RuoYi4.6.0 代码审计
环境布置: 到官网下载源码:https://github.com/yangzongzhuan/RuoYi 采用phpstudy集成数据库,5.7版本。JDK1.8。 IDEA打开项目,等待自动加载,修改application-druid.yml配置文件:数据库名,账…...
C语言入门-选择结构
在编程中,我们经常需要根据不同的条件执行不同的操作。C语言为此提供了几种非常实用的选择结构:条件运算符、逻辑运算、if语句和switch语句。接下来,让我们深入探讨这些重要的知识点,帮助你更好地理解和掌握C语言的选择结构。 1.…...
Legion拯救者 刃7000K-26IAB联想台式机T5 26IAB7(90SU,90SV,90SW,90SX)原厂Windows11系统镜像下载
适用机型:【90SW、90SX、90SU、90SV】 链接:https://pan.baidu.com/s/1gJ4ZwWW2orlGYoPk37M-cg?pwd4mvv 提取码:4mvv lenovo联想原装WIN系统自带所有驱动、出厂主题专用壁纸、系统属性联机支持标志、系统属性专属LOGO标志、Office办公软…...
代码随想录算法训练营第二十四天|Day24 回溯算法
93.复原IP地址 题目链接/文章讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html 视频讲解:https://www.bilibili.com/video/BV1XP4y1U73i/ 思路 char** result; int resultTop; int segments[3]; int isValid(char* s…...
vue elementui table编辑表单时,弹框增加编辑明细数据
需求: 前端进行新增表单时,同时增加表单的明细数据。明细数据部分,通过弹框方式增加或者编辑。 效果图: 代码: <!-- 新增主表弹窗 Begin --><el-dialog:title"titleInfo"top"5vh"centerwidth"…...
springboot集成Redisson做分布式消息队列
这里演示Redisson做分布式消息队列。首先引入 Redisson依赖,官方github <dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.6</version> </dependen…...
如何通过Lua语言请求接口拿到数据
文章目录 概要http客户端通过请求下载数据 概要 当某个需求是需要在模块内请求接口拿到数据,需要使用http客户端调用接口 http客户端 LuaSOC请求接口官方文档 调用:http.request(method,url,headers,body,opts,ca_file,client_ca, client_key, clien…...
Android 13 SystemUI 隐藏下拉快捷面板部分模块(wifi,bt,nfc等)入口
frameworks/base/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java createTileInternal(tileSpec)方法注释想隐藏的模块即可。...
自由学习记录(14)
unity操作问题 位置:子物体的位置是相对于父物体的。如果你移动父物体,子物体会保持相对于父物体的相对位置,跟着一起移动。 旋转:子物体的旋转也是相对于父物体的。旋转父物体会导致子物体围绕父物体的原点旋转。 缩放…...
疯狂Spring Boot讲义[推荐1]
《疯狂Spring Boot讲义》是2021年电子工业出版社出版的图书,作者是李刚 《疯狂Spring Boot终极讲义》不是一本介绍类似于PathVariable、MatrixVariable、RequestBody、ResponseBody这些基础注解的图书,它是真正讲解Spring Boot的图书。Spring Boot的核心…...
小门户网站开发/宁波百度seo排名优化
下面是本篇的大纲: 1、AppWidget 框架类2、在 Android 如何使用 Widget3、AppWidget 框架的主要类介绍4、DEMO 讲解1、AppWidget 框架类 1、AppWidgetProvider :继承自 BroadcastRecevier , 在AppWidget 应用 update、enable、disable 和 del…...
自主建设公司网站/黄冈网站推广策略
开门见山,文档不足 下载下来的是zip包,不是tar包,未能解决 下载 wget https://releases.hashicorp.com/consul/1.3.0/consul_1.3.0_linux_amd64.zip 安装uzip yum -y install wget 解压 unzip consul_1.3.0_linux_amd64.zip 测试 ./c…...
网站平台怎么做的好/网络公司
一、Windows环境下使用.bat安装和卸载服务 win7环境 例子中“”Valwell.Dms.HttpService.exe“”为服务程序名称 安装服务 %SystemRoot%\Microsoft.NET\Framework\v2.0.50727\installutil.exe Valwell.Dms.HttpService.exeNet Start SKMPServicesc config SKMPService start au…...
软件园二期做网站的公司/外贸seo优化公司
oracle 中的常量和变量:变量:通过变量,可以把需要的参数传递进来,经过处理后还可以把值传出去,最终返回给用户。常量:常量是代码中固化的信息,常量的值从定义开始就是固定的。常量主要用于为程序提供固定和…...
应聘网站建设工程师/网络整合营销策划书
1、将accordion设为true,只展开一级 :accordion"true"2、控制默认展开某一项 node-key指定关联字段,并把要展开的字段值以数组的方式复制给属性default-expanded-keys即可 node-key"id" :default-expanded-keys"[1652695]"...
网页设计搜题软件/seo优化快速排名
H5推广的形式中有一个方式是在其中加入明星互动,从刷屏朋友圈的“吴亦凡入伍”,到如今许多的企业品牌都喜欢利用明星在H5中进行互动推广。比如曼妥思-潮清凉:与张艺兴连线视频,碧欧泉:彭于晏需要你的帮助,桂…...