linux入门---信号的保存和捕捉

目录标题

  • 信号的一些概念
  • 信号的保存
    • pending表
    • block表
    • handler表
  • 信号的捕捉
    • 内核态和用户态
    • 信号的捕捉

信号的一些概念

1.进程会收到各种各样的信号,那么程序对该信号进行实际处理的动作叫做信号的递达。
2.我们之前说过当进程收到信号的时候可能并不会立即处理这个信号,而是先将信号进行保存,那么我们把信号从产生到抵达之间的状态称为信号未决。
3.进程可以阻塞某个信号,这样即使发送信号给对应的进程进程也不会做出任何的处理。
4.被阻塞的信号会一直保持在未决的状态,只有当进程解除了对此信号的阻塞时才会执行该信号的动作。
5.阻塞和忽略是两个不同的东西,一个信号要是被阻塞说明即使收到了该信号也不会执行该信号的动作,而忽略是收到该信号之后根据该信号执行的一个动作,只不过该动作是忽略也就是什么都不做而已。

信号的保存

之前的学习中我们知道操作系统是要给每个进程保存收到的信号的,而保存的位置就是task_struct中的一个位图,这是我们当时说的保存方法,但是信号存在三种状态比如说是否收到了信号,是否阻塞了信号,以及信号与之对应的动作以及动作是否被自定义修改了,所以内核使用一张图来保存信号肯定是不够用的,所以在实际的应用中使用了三张表一起来保存了信号,这三个表分别为:pending表,block表和handler表,那么接下来我们来一一介绍这三个表的功能。

pending表

pinding表本质上就是位图,我们之前说进程在运行的任何时候都会收到信号,这个信号并不会被立即处理,所以进程得保存这个信号,保存信号的方式是位图,那么这个位图就是pending表,位图的比特位位置表示哪个信号,比特位的值表示是否收到了该信号,如果收到了信号就将对应位置的值修改为1,如果没有收到信号对应位置的值就是0.

在这里插入图片描述

block表

block表也是一个位图,位图的位置表示信号编号,位图的值表示是否阻塞了对应的信号,被阻塞的信号不会被递达,只有当阻塞被解除了信号才会被递达,即使没有收到对应的信号我们也是可以阻塞一些信号的,这里的逻辑可以用下面的伪代码来表示:

if(1<<(signo)&pcb->block))
{//信号是被阻塞的,不递达
}
else
{if((1<<(signo-1))&pcb->pending){//递达该信号}
}

那这里就可以这么来理解,操作系统会扫描PCB中的位图来判断是否有信号需要被处理,如果信号对应在block上的值为1就直接跳过,如果对应在block上的值为0就接续查看对应在panding位图上的值,如果值为1的活就执行的对应的方法,那么这就是block表的功能。
在这里插入图片描述

handler表

handler表是一个函数指针数组,每个元素都是一个函数指针,数组的位置(下标)表示信号的编号,数组下标对应的内容就表示对应信号的处理方法,signal函数可以修改信号对应的方法,那么这个本质上就是修改handler表对应元素的指向,当信号被递达时就可以根据信号的值来找到handler表中处理信号的方法并执行该方法,那么这里的图片就是下面这样:
在这里插入图片描述

所以看到这里我们可以得出三个结论:如果一个信号没有产生的话,并不妨碍他可以先被阻塞,因为我们只需修改block表中的值跟记录是否收到信号的pending表没有关系,如果阻塞的过程中收到了信号,那么我们就修改pending位图上对应的值并不会接着去找handler表中的方法 2.进程为什么能够识别信号,是因为内核中存在三个表这三个表能让进程认识信号并处理对应的信号。 3.如果SIGQUIT信号未产生过,一旦产生SIGQUIT信号将被阻塞,它的处理动作是用户自定义函数sighandler。如果在进程解除对某信号的阻塞之前这种信号产生过多次,将如何处理?POSIX.1允许系统递送该信号一次或多次。Linux是这样实现的:常规信号在递达之前产生多次只计一次,而实时信号在递达之前产生多次可以依次放在一个队列里。

信号的捕捉

信号产生的时候不会立即被处理,而是在合适的时候被处理,那这个合适的时间是什么时候呢?并且我们上面说到操作系统会在某些时刻检查block表和pending表,那这个时刻又是指的什么时候呢?那么要想解决这些问题我们就得谈谈什么是内核太什么是用户态。

内核态和用户态

我们自己写的代码经过编译和运行之后都是运行在用户态上的,但是在我们在编写代码的时候难免会访问到操作系统的资源(getpid,waitpid)和硬件资源(printf,read,write),当我们访问操作系统的资源或者硬件资源的时候,我们都得直接或者间接的访问系统提供的借口,通过这些接口来访问操作系统的资源,我们把这些接口称为系统调用
在这里插入图片描述
调用系统调用的时候,普通用户不能以自己的身份来调用系统调用,必须将自己的身份变为内核态,
这就好比当我们是一个公司的基层时副总裁的办公室我们几乎不能直接进出,但是当我们的身份变成了公司的CEO时,副总裁的办公室我们就可以随意的进出,所以当我们的身份变成了内核态时我们才能够有资格使用或者访问内核态提供的代码,实际执行系统调用的人是进程,但是身份是内核态,因为用户态调用内核态的时候要发生身份的转换,所以系统调用往往比较费时间一些,所以要尽量避免频繁的调用系统调用
在这里插入图片描述
但是这里存在一个问题,你说进程只是那一个进程,但是却存在两个身份,那该操作系统是如何来实现这一点的呢?那么这里我们就得提到寄存器这个东西

cpu中存在大量的寄存器,寄存器分为两种:1.可见寄存器,2.不可见寄存器,虽然寄存器分为两种但是只要和当前进程强相关的寄存器我们都将其称为上下文数据,比如说cpu中存在一个寄存器专门用来指向当前进程的pcb这样就可以快速的知道当前运行的进程是哪个,再比如说有个寄存器中存储的是当前页表的起始地址,这样就可以快速的找到当前进程的页表,

cpu中还存在一个名为CR3的寄存器,这个寄存器中的内容表征当前进程的运行级别,0表示内核态,3表示用户态,所以想要判断当前的进程是用户态还是内核态就只需要查看CR3里面的内容就行,这里存在一个问题:我是一个进程,进程是怎么跑到内核中执行对应的方法呢?之前我们提到的进程地址空间往往指的是用户空间,我们写的代码存放或者申请空间都是通过用户级地址空间+页表来进行映射,这个空间的大小为3GB
在这里插入图片描述

这里的页表是用户级页表该页表每个进程都有一份,但是地址空间的总大小是4GB,用户级空间只占了3GB那剩下的1GB空间用来干什么呢?我们把这个1GB的空间称为内核级空间,这一块空间也对应了一个页表,这个页表就叫内核级页表,这个页表的作用就是将操作系统级别的代码从内核虚拟地址空间映射到内存上面,
在这里插入图片描述

因为操作系统的代码只有一份,在机器启动的时候会将这份代码加载到内存上,并且每个进程都要使用操作系统代码,所以内核级页表只有一份,每个进程都通过这个页表来映射找到内存上的操作系统的代码,每一个进程都有自己的地址空间(用户空间独占),内核空间(被映射到了每个进程的地址空间的3-4G),所以进程要想访问操作系统的接口,其实只需要在自己的地址空间上进行跳转即可,由用户区跳转到内核区然后再由用户级页表跳转访问内存上的内核代码即可,每一个进程的进程地址空间都有3-4GB的内容,都会共享一个内核级页表,所以无论进程如何切换都不会修改进程地址空间中3-4GB的内容。那用户凭什么能够执行并访问内核的接口或者数据呢?原因是当操作系统发现你要访问内核的数据和代码时,会帮进程修改CR3寄存器的内容,这样就从用户态变成了内核态那么这时就有权利访问内核的数据,那操作系统为什么能知道我们要访问内核的数据和代码呢?答案是当我们要访问操作系统的接口时最开始还是用户态执行的,当以用户态执行系统调用接口时,系统调用接口做的最多的事情还是讲寄存器中的3号状态修改成为0号状态也就是将用户态改成内核态,然后才跳转区域访问内核的数据和代码,那么这就是用户态和内核态的概念

信号的捕捉

我们说操作系统会在合适的时候处理信号,那么这个合适的时候就是从内核态返回用户态的时候对信号进行处理,那么这就说明我们之前一定先进入了内核态,

在这里插入图片描述

当执行系统调用和进程切换(一个进程没有执行完,那一定是放到运行队列或者等待队列,那放进队列的时候一定是以操作系统的身份把我放了进去,所以得先变成内核态 就会变成内核态)
在这里插入图片描述

当操作系统进入内核态并且马上要返回普通状态的时候还会做一件事就是检查内核中的三张表,

在这里插入图片描述

如果block中的信号为0,pending中的信号也为0就会接着检查下一个信号,当block中的值为1就算pending中的值为1的话也不会执行该信号,当block的值为0并且penging的值为1的话就会执行该信号,然后就去handler中查找对应的方法,处理的方法有默认,忽略,自定义,默认的方法中有70%是终止进程,因为当前的身份是内核态所以可以很轻松的终止当前进程,忽略就是要处理该信号,但是处理的动作是什么都不做,所以直接将pending对应位置的信号设置为0就行,自定义的方法的实现在用户态,那这里就存在一个问题:我们能不能以内核态的身份来执行用户的代码呢?从技术的角度上我们可以以内核态的身份访问用户的代码,但是从设计的角度上来看是不能的,因为操作系统不相信任何人,handler方法中可能会有对系统造成危险的操作,而这些操作操作系统是无法识别是安全还是有害的,所以当我们以内核态的身份执行用户的代码的话,这部分代码可能会被恶意分子利用,然后进行一部分越权的非法动作,所以即使从技术上的角度能这么干,操作系统也不让你这么干,所以当要执行自定义代码的时候操作系统得通过特定的调用,将自己的身份从内核态转换称为用户态,然后再执行自定义代码,那么这个时候自定方法出现了问题就是用户自己的问题了,这个时候想干什么坏事情就会收到操作系统的管制了
在这里插入图片描述

执行完自定义方法之后也不能直接返回之前调用方法的地方,因为我们无法知道当初是从哪里进行跳转的,不能从用户态的一个地方跳转到另外一个地方,这里必须得有操作系统的支持,因为在从用户态跳转到内核态的时候操作系统保存了你的上下文信息,所以执行完自定义方法后得从用户态再跳转回内核,再通过特定的系统调用由内核态回到用户态上次的地方再继续向后执行
在这里插入图片描述
那么这就是信号捕捉的全部流程希望大家能够理解。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

计算机考研 | 2016年 | 计算机组成原理真题

文章目录 【计算机组成原理2016年真题44题-9分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题45题-14分】【第一步&#xff1a;信息提取】【第二步&#xff1a;具体解答】 【计算机组成原理2016年真题44题-9分】 假定CPU主频为5…

51单片机可调幅度频率波形信号发生器( proteus仿真+程序+原理图+报告+讲解视频)

51单片机可调幅度频率信号发生器( proteus仿真程序原理图报告讲解视频&#xff09; 讲解视频1.主要功能&#xff1a;2.仿真3. 程序代码4. 原理图4. 设计报告5. 设计资料内容清单&&下载链接***[资料下载链接](https://docs.qq.com/doc/DS1daV1BKRXZMeE9u)*** 51单片机可…

软件工程与计算总结(三)示例项目描述

本节介绍一个标准的项目描述&#xff0c;大家可以作为蓝本学习~ 目录 一.背景 二.目标 三.系统用户 四.用户访谈要点 1.收银员 2.客户经理 3.总经理 4.系统管理员 五.项目实践过程 一.背景 A是一家刚刚发展起来的小型连锁商店&#xff0c;其前身是一家独立的小百货门面…

算法-数学-斜率-直线上最多的点数

算法-数学-斜率-直线上最多的点数 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/max-points-on-a-line/ 1.2 题目描述 给你一个数组 points &#xff0c;其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点。求最多有多少个点在同一条直线上。 2 暴力搜索斜率…

虚拟机VMware的使用流程以及出现的问题附解决方法

虚拟机VMware的使用流程以及出现的问题附解决方法 下载安装 略。。。 创建虚拟机 虚拟机的设置如下&#xff1a;注意网络适配器为NAT 如果出现ip addr 命令&#xff1a;不显示IP地址的话&#xff1a; 解决方式如下&#xff1a; 首先设置网卡&#xff1a;先查看一下onboot是…

OpenCV读取图像时按照BGR的顺序HWC排列,PyTorch按照RGB的顺序CHW排列

OpenCV读取RGB图像 在OpenCV中&#xff0c;读取的图片默认是HWC格式&#xff0c;即按照高度、宽度和通道数的顺序排列图像尺寸的格式。我们看最后一个维度是C&#xff0c;因此最小颗粒度是C。 例如&#xff0c;一张形状为2562563的RGB图像&#xff0c;在OpenCV中读取后的格式…

【Java 进阶篇】JDBC 管理事务详解

在数据库操作中&#xff0c;事务是一个非常重要的概念。事务可以确保一系列的数据库操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;以保持数据库的一致性和完整性。在 Java 中&#xff0c;我们可以使用 JDBC 来管理事务。本文将详细介绍 JDBC 管理事务的方法和…

Leetcode1071. 字符串的最大公因子(三种方法,带详细解析)

Leetcode1071. 字符串的最大公因子 对于字符串 s 和 t&#xff0c;只有在 s t … t&#xff08;t 自身连接 1 次或多次&#xff09;时&#xff0c;我们才认定 “t 能除尽 s”。 给定两个字符串 str1 和 str2 。返回 最长字符串 x&#xff0c;要求满足 x 能除尽 str1 且 x 能…

【面试总结大纲】

面试 1. springSpring AOP的具体实现核心概念分别指的是什么?基于注解的切面实现主要包括以下几个步骤&#xff1a;两个切面&#xff0c;它们之间的顺序是怎么控制的 springmvc的工作流程设计模式原则Spring 框架中用到了哪些设计模式&#xff1f; 2. Java-锁2.1锁的分类可重入…

开发调试管理系统遇到的问题大全错误解决大全收集

问题大全错误解决大全 多模块项目依赖中&#xff0c;项目启动失败-org.yaml.snakeyaml.error.YAMLException: java.nio.charset.MalformedInputException报错&#xff1a;Error: The project seems to require yarn but it‘s not installednpm ERR! fatal: Could not read fro…

动态规划-状态机(188. 买卖股票的最佳时机 IV)

状态分类&#xff1a; f[i,j,0]考虑前i只股票&#xff0c;进行了j笔交易&#xff0c;目前未持有股票 所能获得最大利润 f[i,j,1]考虑前i只股票&#xff0c;进行了j笔交易&#xff0c;目前持有股票 所能获得最大利润 状态转移&#xff1a; f[i][j][0] Math.max(f[i-1][j][0],f[…

Linux高性能服务器编程 学习笔记 第十章 信号

信号是由用户、系统、进程发送给目标进程的信息&#xff0c;以通知目标进程某个状态的改变或系统异常。Linux信号可由以下条件产生&#xff1a; 1.对于前台进程&#xff0c;用户可通过输入特殊终端字符来给它发送信号&#xff0c;如输入CtrlC通常会给进程发送一个中断信号。 2…

视频讲解|基于DistFlow潮流的配电网故障重构代码

目录 1 主要内容 2 视频链接 1 主要内容 该视频为基于DistFlow潮流的配电网故障重构代码讲解内容&#xff0c;对应的资源下载链接为基于DistFlow潮流的配电网故障重构(输入任意线路)&#xff0c;对该程序进行了详尽的讲解&#xff0c;基本做到句句分析和讲解&#xff08;讲解…

双重差分模型(DID)论文写作指南与操作手册

手册链接&#xff1a;双重差分模型&#xff08;DID&#xff09;论文写作指南与操作手册https://www.cctalk.com/m/group/90983583?xh_fshareuid60953990 简介&#xff1a; 当前&#xff0c;对于准应届生们来说&#xff0c;毕设季叠加就业季&#xff0c;写作时间显得十分宝贵…

Polygon Miden zkRollup中的UTXO+账户混合状态模型

1. 引言 本文重点讨论Polygon Miden所设计的UTXO账户混合状态模型&#xff0c;以实现某些有趣的属性。 Miden的目标是&#xff1a;【即越具有隐私性&#xff0c;其可扩展性越好】 构建可扩展去中心化的rollup采用支持隐私的架构 Miden支持灵活的交易模式&#xff1a; 公开…

QT实现TCP服务器客户端的实现

ser&#xff1a; widget.cpp&#xff1a; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//实例化一个服务器server new QTcpServer(this);// 此时&#xf…

软件设计师_计算机网络_学习笔记

文章目录 4.1 网路技术标准与协议4.1.1 协议4.1.2 DHCP4.1.3 DNS的两种查询方式 4.2 计算机网络的分类4.2.1 拓扑结构 4.3 网络规划与设计4.3.1 遵循的原则4.3.2 逻辑网络设计4.3.3 物理网络设计4.3.4 分层设计 4.4 IP地址与子网划分4.4.1 子网划分4.4.2 特殊IP 4.5 HTML4.6 无…

BL808学习日志-2-LVGL for M0 and D0

一、lvgl测试环境 对拿到的M1S_DOCK开发板进行开发板测试&#xff0c;博流的官方SDK是支持M0和D0两个内核都进行测试的&#xff1b;但是目前只实现了M0的LVGLBenchmark&#xff0c;测试D0内核中发现很多莫名其妙的问题。一会详细记录。 使用的是开发板自带的SPI显示屏&#xff…

STM32复习笔记(五):FSMC连接外部SRAM

目录 Preface&#xff1a; &#xff08;一&#xff09;原理相关 &#xff08;二&#xff09;CUBEMX配置 &#xff08;三&#xff09;轮询方式读写 &#xff08;四&#xff09;DMA方式读写 Preface&#xff1a; STM32F4有一个FSMC&#xff08;Flexible Static Memory Contr…

C++ YAML使用

C++工程如何使用YAML-cpp 一、前期准备工作 1、已安装minGW、cmake、make等本地工具。 2、下载YAML-cpp第三方开源代码(一定要下载最新的release版本,不然坑很多)。 3、生成YAML-cpp静态库 (1)在yaml-cpp-master下建立build文件夹; (2)在该文件夹下生成MakaFile文…