Linux进程 ----- 信号处理

目录

前言

一、信号的处理时机

1.1 处理时面临的情况

1.2 “合适”的时机

二、用户态与内核态

2.1 概念理论

2.2 再现 进程地址空间

2.3 信号处理过程

三、信号的捕捉

3.1 内核实现

3.2 sigaction

四、信号部分小结


前言

从信号产生到信号保存,中间经历了很多,当操作系统准备对信号进行处理时,还需要判断时机是否 “合适”,在绝大多数情况下,只有在 “合适” 的时机才能处理信号,即调用信号的执行动作。

一、信号的处理时机

1.1 处理时面临的情况

普通情况

所谓的普通情况就是指 信号没有被阻塞,直接产生,记录未决信息后,再进行处理

在这种情况下,信号是不会被立即递达的,也就无法立即处理,需要等待合适的时机。

特殊情况

当信号被 阻塞 后,信号 产生 时,记录未决信息,此时信号被阻塞了,也不会进行处理

当阻塞解除后,信号会被立即递达,此时信号会被立即处理

普通情况 就有点难搞了,它需要等待 “合适” 的时机,才能被 递达,继而被 处理

1.2 “合适”的时机

信号的产生是 异步 的

        也就是说,信号可能随时产生,当信号产生时,进程可能在处理更重要的事,此时贸然处理信号显然不够明智

比如进程正在执行一个重要的 IO,突然一个终止信号发出,IO 立即终止,对进程、磁盘都不好

因此信号在 产生 后,需要等进程将 更重要 的事忙完后(合适的时机),才进行 处理

合适的时机:进程从 内核态 返回 用户态 时,会在操作系统的指导下,对信号进行检测及处理

至于处理动作,分为:默认动作、忽略、用户自定义

搞清楚 “合适” 的时机 后,接下来需要学习 用户态 和 内核态 相关知


二、用户态与内核态

对于 用户态、内核态 的理解及引出的 进程地址空间 和 信号处理过程 相关知识是本文的重难点

2.1 概念理论

先来看看什么是 用户态和内核态

  • 用户态:执行用户所写的代码时,就属于 用户态
  • 内核态:执行操作系统的代码时,就属于 内核态

自己写的代码被执行很好理解,操作系统的代码是什么?

  • 操作系统也是由大量代码构成的
  • 在对进程进行调度、执行系统调用、异常、中断、陷阱等,都需要借助操作系统之手
  • 此时执行的就是操作系统的代码

也就是说,用户态 与 内核态 是两种不同的状态,必然存在相互转换的情况

用户态 切换为 内核态

  • 当进程时间片到了之后,进行进程切换动作
  • 调用系统调用接口,比如 open、close、read、write 等
  • 产生异常、中断、陷阱等

内核态 切换为 用户态

  • 进程切换完毕后,运行相应的进程
  • 系统调用结束后
  • 异常、中断、陷阱等处理完毕

信号的处理时机就是 内核态 切换为 用户态,也就是 当把更重要的事做完后,进程才会在操作系统的指导下,对信号进行检测、处理

下面来结合 进程地址空间 深入理解 操作系统的代码 及 状态切换 的相关内容(拓展知识)

2.2 再现 进程地址空间

首先简单回顾下 进程地址空间 的相关知识:

  • 进程地址空间 是虚拟的,依靠 页表+MMU机制 与真实的地址空间建立映射关系
  • 每个进程都有自己的 进程地址空间,不同 进程地址空间 中地址可能冲突,但实际上地址是独立的
  • 进程地址空间 可以让进程以统一的视角看待自己的代码和数据

不难发现,在 进程地址空间 中,存在 1 GB 的 内核空间,每个进程都有,而这 1 GB 的空间中存储的就是 操作系统 相关 代码 和 数据,并且这块区域采用 内核级页表 与 真实地址空间 进行映射

为什么要区分 用户态 与 内核态 ?

  • 内核空间中存储的可是操作系统的代码和数据,权限非常高,绝不允许随便一个进程对其造成影响
  • 区域的合理划分也是为了更好的进行管理

所谓的 执行操作系统的代码及系统调用,就是在使用这 1 GB 的内核空间

进程间具有独立性,比如存在用户空间中的代码和数据是不同的,难道多个进程需要存储多份操作系统的代码和数据吗?

  • 当然不用,内核空间比较特殊,所有进程最终映射的都是同一块区域,也就是说,进程只是将 操作系统代码和数据 映射入自己的 进程地址空间 而已
  • 而 内核级页表 不同于 用户级页表,专注于对 操作系统代码和数据 进行映射,是很特殊的

当我们执行诸如 open 这类的 系统调用 时,会跑到 内核空间 中调用对应的函数

而 跑到内核空间 就是 用户态 切换为 内核态 了(用户空间切换至内核空间

这个 跑到 是如何实现的呢?

在 CPU 中,存在一个 CR3 寄存器,这个 寄存器 的作用就是用来表征当前处于 用户态 还是 内核态

  • 当寄存器中的值为 3 时:表示正在执行用户的代码,也就是处于 用户态
  • 当寄存器中的值为 0 时:表示正在执行操作系统的代码,也就是处于 内核态

通过一个 寄存器,表征当前所处的 状态,修改其中的 ,就可以表示不同的 状态,这是很聪明的做法

那么进程又是如何被调度的呢?

  1. 操作系统的本质
    操作系统也是软件啊,并且是一个死循环式等待指令的软件
    存在一个硬件:操作系统时钟硬件,每隔一段时间向操作系统发送时钟中断
  2. 进程被调度,就意味着它的时间片到了,操作系统会通过时钟中断,检测到是哪一个进程的时间片到了,然后通过系统调用函数 schedule() 保存进程的上下文数据,然后选择合适的进程去运行

2.3 信号处理过程

当在 内核态 完成某种任务后,需要切回 用户态,此时就可以对信号进行 检测 并 处理 了

情况1:信号被阻塞,信号产生/未产生

信号都被阻塞了,也就不需要处理信号,此时不用管,直接切回 用户态 就行了

情况2:当前信号的执行动作为 默认

大多数信号的默认执行动作都是 终止 进程,此时只需要把对应的进程干掉,然后切回 用户态 就行了

情况3:当前信号的执行动作为 忽略

当信号执行动作为 忽略 时,不做出任何动作,直接返回 用户态

情况4:当前信号的执行动作为 用户自定义

这种情况就比较麻烦了,用户自定义的动作位于 用户态 中,也就是说,需要先切回 用户态,把动作完成了,重新坠入 内核态,最后才能带着进程的上下文相关数据,返回 用户态

在 内核态 中,也可以直接执行 自定义动作,为什么还要切回 用户态 执行自定义动作?

  • 因为在 内核态 可以访问操作系统的代码和数据,自定义动作 可能干出危害操作系统的事
  • 在 用户态 中可以减少影响,并且可以做到溯源

为什么不在执行完 自定义动作 直接后返回进程?

  • 因为 自定义动作 和 待返回的进程 属于不同的堆栈,是无法返回的
  • 并且进程的上下文数据还在内核态中,所以需要先坠入内核态,才能正确返回用户态

注意: 用户自定义的动作,需要先切换至 用户态 中执行,执行结束后,还需要坠入 内核态

三、信号的捕捉

3.1 内核实现

如果信号的执行动作为 用户自定义动作,当信号 递达 时调用 用户自定义动作,这一动作称为 信号捕捉

用户自定义动作 是位于 用户空间 中的

        当 内核态 中任务完成,准备返回 用户态 时,检测到信号 递达,并且此时为 用户自定义动作,需要先切入 用户态 ,完成 用户自定义动作 的执行;因为 用户自定义动作 和 待返回的函数 属于不同的 堆栈 空间,它们之间也不存在 调用与被调用 的关系,是两个 独立的执行流,需要先坠入 内核态 (通过 sigreturn() 坠入),再返回 用户态(通过 sys_sigreturn() 返回)

3.2 sigaction

sigaction 也可以 用户自定义动作,比 signal 功能更丰富

#include <signal.h>int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);struct sigaction 
{void     (*sa_handler)(int);	//自定义动作void     (*sa_sigaction)(int, siginfo_t *, void *);	//实时信号相关,不用管sigset_t   sa_mask;	//待屏蔽的信号集int        sa_flags;	//一些选项,一般设为 0void     (*sa_restorer)(void);	//实时信号相关,不用管
};

返回值:成功返回 0,失败返回 -1 并将错误码设置

参数1:待操作的信号

参数2:sigaction 结构体,具体成员如上所示

参数3:保存修改前进程的 sigaction 结构体信息

这个函数的主要看点是 sigaction 结构体

struct sigaction 
{void     (*sa_handler)(int);	//自定义动作void     (*sa_sigaction)(int, siginfo_t *, void *);	//实时信号相关,不用管sigset_t   sa_mask;	//待屏蔽的信号集int        sa_flags;	//一些选项,一般设为 0void     (*sa_restorer)(void);	//实时信号相关,不用管
};

其中部分字段不需要管,因为那些是与 实时信号 相关的,我们这里不讨论

sa_mask当信号在执行 用户自定义动作 时,可以将部分信号进行屏蔽,直到 用户自定义动作 执行完成

也就是说,我们可以提前设置一批 待阻塞 的 屏蔽信号集,当执行 signum 中的 用户自定义动作 时,这些 屏蔽信号集 中的 信号 将会被 屏蔽(避免干扰 用户自定义动作 的执行),直到 用户自定义动作 执行完成

四、信号部分小结

截至目前,信号 处理的所有过程已经全部学习完毕了

信号产生阶段:有四种产生方式,包括 键盘键入、系统调用、软件条件、硬件异常

信号保存阶段:内核中存在三张表,blcok 表、pending 表以及 handler 表,信号在产生之后,存储在 pending 表中

信号处理阶段:信号在 内核态 切换回 用户态 时,才会被处理

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

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

相关文章

计算机网络-后退N帧协议(弊端 滑动窗口 运行中的GBN 滑动窗口长度习题 GBN协议性能分析 )

文章目录 停等协议的弊端后退N帧协议中的滑动窗口GBN发送方必须响应的三件事GBN接受方要做的事运行中的GBN滑动窗口长度GBN协议重点总结习题1习题2GBN协议性能分析小结 停等协议的弊端 信道利用率低&#xff1a;在停等协议中&#xff0c;发送方在发送完一帧后必须等待接收方确…

高防IP简介

高防IP可以防御的有包括但不限于以下类型&#xff1a; SYN Flood、UDP Flood、ICMP Flood、IGMP Flood、ACK Flood、Ping Sweep 等攻击。高防IP专注于解决云外业务遭受大流量DDoS攻击的防护服务。支持网站和非网站类业务的DDoS、CC防护&#xff0c;用户通过配置转发规则&#x…

蓝桥杯备战刷题one(自用)

1.被污染的支票 #include <iostream> #include <vector> #include <map> #include <algorithm> using namespace std; int main() {int n;cin>>n;vector<int>L;map<int,int>mp;bool ok0;int num;for(int i1;i<n;i){cin>>nu…

项目:shell实现多级菜单脚本编写

目录 1. 提示 2. 演示效果 2.1. 一级菜单 2.2. 二级菜单 2.3. 执行操作 3. 参考代码 1. 提示 本脚本主要实现多级菜单效果&#xff0c;并没有安装LAMP、LNMP环境&#xff0c;如果要用在实际生成环境中部署LNMP、LAMP环境&#xff0c;只需要简单修改一下就可以了。 2. 演…

Mysql运维篇(五) 部署MHA--主机环境配置

一路走来&#xff0c;所有遇到的人&#xff0c;帮助过我的、伤害过我的都是朋友&#xff0c;没有一个是敌人。如有侵权&#xff0c;请留言&#xff0c;我及时删除&#xff01; 大佬博文 https://www.cnblogs.com/gomysql/p/3675429.html MySQL 高可用&#xff08;MHA&#x…

php伪协议 [SWPUCTF 2022 新生赛]ez_ez_php(revenge)

打开题目 题目源代码如下 <?php error_reporting(0); if (isset($_GET[file])) {if ( substr($_GET["file"], 0, 3) "php" ) {echo "Nice!!!";include($_GET["file"]);} else {echo "Hacker!!";} }else {highlight_fi…

【高德地图】Android高德地图控件交互详细介绍

&#x1f4d6;第5章 与地图控件交互 ✅控件交互&#x1f9ca;缩放按钮&#x1f9ca;指南针&#x1f9ca;定位按钮&#x1f9ca;地图Logo ✅手势交互&#x1f9ca;缩放手势&#x1f9ca;滑动手势&#x1f9ca;旋转手势&#x1f9ca;倾斜手势&#x1f9ca;指定屏幕中心点的手势操…

C语言中strstr函数的使用!

strstr函数的作用是什么&#xff1f; 查找子字符串 具体直接看下面的这段代码我相信你必明白 #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> int main() { char *p1 "abcdefghijklmnopqrstuvwxyz"; char* p2 "abc"; char* r…

智慧公厕让社区生活更美好

随着科技的迅猛发展&#xff0c;城市管理、城市服务均使用科技化的手段进行升级改造&#xff0c;社区生活更美好赋予全新的智慧效能&#xff0c;其中智慧公厕也成为了城市环卫设施的新宠。智慧公厕以物联网、互联网、大数据、云计算、5G通信、自动化控制等技术为核心&#xff0…

LLM (Large language model)的指标参数

1. 背景介绍 我们训练大模型的时候&#xff0c;或者我们用RAG的时候&#xff0c;不知道我们的算法&#xff0c;或者我们的提示&#xff0c;或者我们的本地知识库是否已经整理得符合要求了。又或我们需要一个指标去评估我们目前的所有围绕大模型&#xff0c;向量数据库或外挂知…

【可实战】被测系统业务架构、系统架构、技术架构、数据流、业务逻辑分析

一、为什么要学习 更深的理解业务逻辑&#xff08;公司是做什么的&#xff1f;它最重要的商务决策是什么&#xff1f;它里面的数据流是怎么做的&#xff1f;有哪些业务场景&#xff1f;考验你对这家公司、对所负责业务的熟悉程度。公司背后服务器用什么软件搭建的&#xff1f;…

高性能API云原生网关 APISIX安装与配置指南

Apache APISIX是Apache软件基金会下的顶级项目&#xff0c;由API7.ai开发并捐赠。它是一个高性能的云原生API网关&#xff0c;具有动态、实时等特点。 APISIX网关可作为所有业务的流量入口&#xff0c;为用户提供了丰富的功能&#xff0c;包括动态路由、动态上游、动态证书、A…

【C语言基础】:操作符详解(一)

文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…

神经网络系列---激活函数

文章目录 激活函数Sigmoid 激活函数Tanh激活函数ReLU激活函数Leaky ReLU激活函数Parametric ReLU激活函数 &#xff08;自适应Leaky ReLU激活函数&#xff09;ELU激活函数SeLU激活函数Softmax 激活函数Swish 激活函数Maxout激活函数Softplus激活函数 激活函数 一般来说&#xf…

Unity零基础到进阶 | Unity中的 RectTransformUtility 方法整理汇总

Unity零基础到进阶 ☀️| RectTransformUtility 方法整理汇总一、RectTransformUtility 官方文档1.1 RectTransformUtility.CalculateRelativeRectTransformBounds&#xff08;重&#xff09;1.2 RectTransformUtility.FlipLayoutAxes1.3 RectTransformUtility.FlipLayoutOnAxi…

python:xml.etree.ElementTree 读 Freeplane.mm文件,生成测试案例.csv文件

Freeplane 是一款基于 Java 的开源软件&#xff0c;继承 Freemind 的思维导图工具软件&#xff0c;它扩展了知识管理功能&#xff0c;在 Freemind 上增加了一些额外的功能&#xff0c;比如数学公式、节点属性面板等。 强大的节点功能&#xff0c;不仅仅节点的种类很多&#xf…

XSS原理和攻防

Cross Site Scripting:跨站脚本攻击 用户提交的数据中可以构造恶意代码&#xff0c;并且执行&#xff0c;从而实现窃取用户信息等攻击 攻击&#xff1a; 防御&#xff1a; 1.对输入进行过滤&#xff0c;对输出进行编码 2.cookie设置http-only

Nest.js权限管理系统开发(八)jwt登录

安装相关依赖 虽然仅使用nestjs/jwt就能实现身份验证的功能&#xff0c;但是使用passport能在更高层次上提供更多便利。Passport 拥有丰富的 strategies 生态系统&#xff0c;实现了各种身份验证机制。虽然概念简单&#xff0c;但你可以选择的 Passport 策略集非常丰富且种类繁…

(HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕

一、电路接法 电路接法参照江科大视频。 二、相关代码及文件 说明&#xff1a;代码采用hal库&#xff0c;通过修改江科大代码实现。仅OLED.c文件关于引脚定义作了hal库修改&#xff0c;并将宏定义OLED_W_SCL(x)、OLED_W_SDA(x)作了相关修改。 1、OLED.c void OLED_I2C_Init(voi…

自动化行业文件数据\资料防泄密软件——天锐绿盾|@德人合科技

天锐绿盾是一款自动化行业文件数据防泄密软件&#xff0c;由德人合科技提供。该软件采用动态加解密技术&#xff0c;能够有效防止公司内部数据泄密&#xff0c;同时支持各种文件格式加密&#xff0c;如CAD、OFFICE、PDF、图纸等。 PC端&#xff1a;https://isite.baidu.com/sit…