学习系统编程No.26【信号处理实战】

引言:

北京时间:2023/6/26/13:35,昨天12点左右睡觉,本以为能和在学校一样,7点左右起床,设置了7点到8点30时间段内的4个闹钟,可惜没想到啊,没醒,直接睡到了12点,看来下次不能给自己太高的期望,哈哈哈!在家没办法呀,习惯睡到12点了,想要解决这个问题,最好的方法就是早睡,今天争取在11点前睡觉,然后看看明天能不能在8点前起床,作息必须调整成和学校一样,这样才不会耽误我们更新博客,上篇博客是这个月16号就要写完的,可惜硬是拖到25号才发,由于考试和放假等原因,摆烂至今,哎,无奈!但,一切还有待挽回,只要把这个暑假给利用好,那么就无伤大雅,无论是为了今天能够早睡,还是实现自己的期望,正式进入该篇博客的主题,剩余相关信号产生和信号保存、信号处理等知识讲解。

在这里插入图片描述

信号产生剩余知识

上篇博客由于各种原因,剩下了许多知识没有讲解完,那么只能在该篇博客中进行回顾和深入,但本质都已经讲解过了,只不过是进行一定的深入和概念转换而已,所以接下来,我们就把先把上篇博客剩余有关知识进行讲解,然后再学习有关线程相关的知识吧!

什么是云服务器
谈到云服务器,当时在学习Linux时,购买了一个腾讯云的云服务器,至今已经快要过期了,当时只购买了半年,早知道买一年甚至两年了,续费价格挺让我苦恼的,哈哈哈!不过问题不大,在该篇博客我们只要知道,云服务器是基于虚拟化技术的计算资源,通过云平台提供灵活的计算、存储和网络资源。可以为用户提供一种高效、可靠和经济的方式来托管应用程序、运行服务以及处理大规模的计算任务,优势在于灵活性、可扩展性、弹性伸缩以及简化的部署和管理过程。云服务器这么好用,也这么有用,可惜我对其功能的使用方式可以说是一窍不通,只知道用来登录一下Linux系统,哈哈哈,想笑,具体能玩出什么花样来,在没接触过之前,我也不晓得,但是我知道肯定很厉害,具体需要我们深入学习,等接触了网络等知识时,才能有一定的自我理解,并且云服务器相关知识在之后的博客中,我们也会重点了解,这里不过多介绍。

获取core dump标志位
无论是在上篇博客,还是之前学习有关进程控制和进程等待相关知识时,我们都知道,可以通过waitpid获取到一个进程的退出状态,并且由于该退出状态是一个位图结构,该位图结构又包含了退出信号、退出码和core dump标志位等信息,所以此时我们就可以通过对该退出状态的位图结构进行位运算,得出对应的退出信号、退出码和core dump标志位,如下代码所示:
在这里插入图片描述
注意:如果是使用云服务器,同理,一定先要将对应的核心转储功能给打开,只有打开之后,发送对应的Core行为状态信号,操作系统才会发生核心转储功能,如上图所示,具体关闭和打开云服务去上的核心转储功能,在上篇博客中我们有详解介绍,这里就不多做赘述,并且core dump标志位,我们具体也见到了,有关core dump相关知识,我们就讲到这里,下面正式进入另一块重要知识学习。

什么叫做阻塞信号

注意,此时的这个阻塞信号和我们之前学习的有关进程状态(阻塞,挂起)毫无关系,该知识是一块全新的知识,并没有任何相似知识,要进行区分,不过,这块知识和我们之前学习有关信号在进程pcb中存储肯定是有一定关系的,在之前的博客中,我们就学习了相关信号执行和存储等知识,当然有信号存储,信号执行,那么肯定存在着信号阻塞或者是信号忽略等概念的存在,所以下述知识也算是在完善信号相关知识,具体如下所述。

信号其它相关常见概念

同理,在之前,我们学习了相关信号执行动作(默认、自定义、忽略),但是在计算机中,信号在被执行中,还存在着许多的概念,如信号递达,信号未决,信号阻塞等!虽然听着这些概念非常的高大上,但本质这些概念分别表示什么内容,我们都已经熟练掌握了,如下:

信号递达(delivery):执行信号的处理动作,当然也就是上述所说的三种信号执行动作,默认处理动作,自定义处理动作,忽略动作本质都是一种信号递达行为,总的来说信号递达就是收到信号后会执行某一个动作
信号未决(pending):信号从产生到递达之间的状态,当然也就是之前所说信号产生之后,操作系统将信号编号写入进程pcb对应位图结构,等待进程执行该信号的过程
信号阻塞:同理,进程可以选择阻塞某个信号,被阻塞信号将保持在未决状态,直到进程解除对该信号的阻塞,该信号才可被递达(注意忽略不叫做阻塞)

那么具体如何理解进程阻塞信号呢?
本质就是因为在信号递达过程中,操作系统可以向进程pcb中写入任意一个信号,那么这也就决定着,操作系统可以选择让该进程阻塞某一个或者多个信号,这样做的意义在于,当该进程会导致操作系统产生某个信号,或者操作系统会发送某个信号给该进程,那么由于该进程对该信号设置了阻塞,此时该进程就允许不再递达该信号,直到该信号被解除相应的阻塞状态,该信号才允许被递达。注意:如果某一个信号处于阻塞状态,那么该信号一定未决,但信号阻塞并不会影响信号未决(好比你不做作业,但是并不影响老师给你布置作业),并且信号阻塞也叫作信号屏蔽。

如何理解忽略动作
在日常生活中,忽略动作表示你知道某件事需要你去完成,但你却消极对待,不重视,不关心,例如:老师布置了一份作业,你将作业记在了笔记本上,但你在完成它时,就直接用线划掉,表示自己完成了该作业。而在Linux操作系统看来,忽略动作,本质就是使用signal系统调用接口让某一个信号的默认执行动作从终止进程变为忽略,也就意味着忽略动作就是将某个信号通过signal函数接口将其默认动作设置为SIG_IGN,当然此时的SIG_IGN表示的就是信号忽略。同理注意:虽然信号忽略和信号阻塞都是什么都不干,但是信号阻塞,那么该信号一定是处于非递达状态,而信号忽略,该信号却是处于递达状态。

信号保存

搞定了上述知识,此时进入信号相关知识中最后一部分,当然也是最重要的一部分知识,信号保存,无论是在上述讲解中,还是在之前的学习过程中,都一直强调进程保存信号的知识和操作系统向进程写入信号的知识,操作系统是如何写入信号,我们通过对位图结构的理解,有了一定的了解,但是对于进程pcb中的位图结构具体是如何保存该信号,我们并不清楚,所以接下来我们就深入探讨一下有关进程进行信号保存的相关知识吧!如下:

首先明白,对于操作系统来说,管理一个进程,最重要的就是管理该进程的进程pcb,而某一个进程的进程pcb是非常复杂的,其中包含了该进程对应的各种数据,内容较为繁杂,其中对于存储信号来说,在进程pcb(task_struct)中,存在着一张表,如下图所示:
在这里插入图片描述
如上图所示,此时我们就意识到,之前我们了解的有关信号保存,只是让对应的信号编号通过操作系统写入到pending位图中,同理pending位图中比特位的位置表示的就是对应的信号编号,比特位的内容表示的就是该信号是否被写入。并且发现除了pending表,还存在另外两种表,其中阻塞表表示该信号是否被阻塞,只有在未被阻塞的前提下,该信号才会发生递达,如果该信号被阻塞,那么就算该信号存在于pending表中,也不会被递达,最后就是自定义动作表,该表表示的是一个数组,该数组的数组下标同理表示信号编号,下标内容表示信号递达动作(函数指针),同理可以是默认动作,也可以是自定义动作或者忽略动作,具体该下标中的递达动作是什么,我们可以通过系统调用接口signal进行替换,但一般是SIG_DFL(默认动作)。此时明白了上述三张表分别代表什么之后,我们就可以发现,一个信号在进程中是如何被保存和一个进程是如何识别一个信号,也就是明确该信号应该如何被执行,是否阻塞,是否执行默认动作,并且可以很好的明白,底层实现代码本质就是在通过判断语句(if)进行判断,最终判断一个信号符合那种情况,然后被进程执行而已。

详解信号列表
在这里插入图片描述

什么是sigset_t

明白上述pending和block两个位图结构,是允许我们直接进行控制的,只不过由于它们属于位图结构,所以如果我们想要对其进行控制,就需要使用位图数据类型,当然也就是sigset_t数据类型,并且明白sigset_t也叫做信号集,而用于控制pending位图结构的叫做未决信号集,用于控制block位图结构的叫做阻塞信号集,本质来说,sigset_t就是用于控制内核中的block和pending两张位图结构表,但,由于我们自己进行位运算,容易出现一系列的问题,为了避免这个问题,操作系统提供了许多的位运算接口给我们使用,如下代码所示:

int sigemptyset(sigset_t *set);
int sigfillset(sigset_t *set);
int sigaddset (sigset_t *set, int signo);
int sigdelset(sigset_t *set, int signo);
int sigismember(const sigset_t *set, int signo);

总而言之:上述几个接口就是用于控制位图结构,也就是对sigset_t类型的数据进行增删查改,可以通过上述接口设计出任意的符合我们要求的位图结构。

信号集读取控制函数

明白了上述知识,此时我们就知道,对于位图结构来说,也存在相对应的增删查改操作,可以使用相对应的接口对位图结构进行控制,所以同理上述所说,如果我们需要控制block或者pending表,就可以使用相对应的接口,但是此时会面临一个问题,那就是如何获取到block或pending位图结构,并且将其修改呢?所以接下来就涉及到两个信号集读取控制函数,如下所述:

1.sigprocmask
其中 sigprocmask 是一个用来读取并且修改block表的函数接口,头文件signal.h,基本调用方式:int sigprocmask(int how, const sigset_t *set, sigset_t *oset);其中第一个参数how表示想怎么改,其中附带了三个参数选项,SIG_BLOCK、SIG_UNBLOCK、SIG_SETMASK,其中SIG_BLOCK表示的是将某一个信号编号添加到阻塞信号集(block)中,而SIG_UNBLOCK表示的是将某一个信号从阻塞信号集中解除阻塞,SIG_SETMASK表示的是直接将一个位图结构替换阻塞信号集(block位图),具体如下代码所示:
在这里插入图片描述
从上图我们就可以发现,在sigprocmask中,该接口的第二个参数表示的是一个sigset_t类型的位图结构,该位图结构的目的就是用于控制block位图结构,通过SIG_BLOCK、SIG_UNBLOCK、SIG_SETMASK等选项实现与其对应的位运算,并且其中SIG_BLOCK表示的就是mask|=set,SIG_UNBLOCK表示的就是mask&=~set,SIG_SETMASK表示的就是mask^=set,而最后一个参数oset表示的就是没有进行位运算之前的block位图结构,作为的是一个输出型参数,方便之后将位图结构复原(当然也就是解除阻塞状态或者是重新将某个信号编号设置为阻塞状态),本质也就是获取调用sigprocmask接口之前的block位图结构。

2.sigpending
明白上述sigprocmask接口是用于读取和控制阻塞信号集(block表),那么同理,pending表也需要被读取和控制,此时控制pending表的接口就叫做 sigpending ,同理头文件signal.h,基本使用方式:int sigpending(sigset_t* set);显然此时通过该调用方式,发现,该接口只有一个参数,所以此时间接明白,该接口不允许我们直接修改pending位图,而只支持我们获取pending位图,和sigprocmask接口不同的是,sigprocmask接口不仅支持我们获取block位图结构,还支持我们修改该位图结构,本质也就是操作系统支持我们对某个进程进行阻塞某个信号的操作,而不支持我们直接向进程写入信号的操作,所以该接口的目的非常的简单,为了提供我们pending位图结构,也就是可以让我们知道,目前该进程中有哪些信号正处于pending(未决)状态。如下代码所示:
在这里插入图片描述
当然由于上述我们在屏蔽信号时,只屏蔽了2号信号,所以才会导致发送2号信号该进程不被终止的同时,pending位图的2号比特位由0置1,当然同理,我们也可以将1到31号信号全部给屏蔽掉,但是此时会发现,有的信号就算是被屏蔽了,进程也会执行该信号的默认动作,所以明白,对于操作系统和进程来说,有的信号不允许用户自定义控制,就算该信号被阻塞,其依然需要执行。

总结:有关信号产生、信号保存和信号处理相关知识该篇博客就介绍到这啦,因为时间关系,剩余知识同理下篇博客见,啦啦啦啦!

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

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

相关文章

【复习30-35题】【每天40分钟,我们一起用50天刷完 (剑指Offer)】第二十一天 21/50

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客,如有问题交流,欢迎评论区留言,一定尽快回复!(大家可以去看我的专栏,是所有文章的目录)   文章字体风格: 红色文字表示&#…

Paddle OCR 安装使用教程

文章目录 一、简介二、使用教程三、模型调用四、效果展示 一、简介 PaddleOCR是飞浆开源文字识别模型,最新开源的超轻量PP-OCRv3模型大小仅为16.2M。同时支持中英文识别;支持倾斜、竖排等多种方向文字识别;支持GPU、CPU预测,并且…

阿里内部《Java工程师面试手册》火了,完整版 PDF 开放下载

前言 2023金九银十即将来临,很多同学会问Java面试八股文有必要背吗? 我的回答是:很有必要。你可以讨厌这种模式,但你一定要去背,因为不背你就进不了大厂。 国内的互联网面试,恐怕是现存的、最接近科举考…

el-input输入框type=“number“时,禁止鼠标上下滑动改变数值

el-input输入框type"number"时,禁止鼠标上下滑动改变数值 解决方法:在el-input中添加属性设置 mousewheel.native.prevent

深度学习实例分割篇——Mask RCNN原理详解篇

🍊作者简介:秃头小苏,致力于用最通俗的语言描述问题 🍊专栏推荐:深度学习网络原理与实战 🍊近期目标:写好专栏的每一篇文章 🍊支持小苏:点赞👍🏼、…

Rust 第三天---内存管理与所有权

前面介绍了环境配置以及基础语法,掌握之后已经可以开始用Rust编写一些简单的程序了,今天就要来介绍一下Rust核心的功能—内存管理与所有权 1. 关于内存管理 无论什么高级语言必须考虑到的一点就是编写程序时对于内存的管理问题,更简单一点解释,利用编程语言能快速高效的分配内…

【零基础入门学习Python---Python中机器学习和人工智能之快速入门实践】

🚀 零基础入门学习Python🚀 🌲 算法刷题专栏 | 面试必备算法 | 面试高频算法 🍀 🌲 越难的东西,越要努力坚持,因为它具有很高的价值,算法就是这样✨ 🌲 作者简介:硕风和炜…

GitHub Pages + Hexo

步骤 参考如下步骤:https://blog.csdn.net/yaorongke/article/details/119089190 出现的问题 1 Fluid主题 其更换Fluid主题时: 下载最新 release 版本 解压到 themes 目录,并将解压出的文件夹重命名为 fluid 按照上面执行后,后…

历史上的今天发生了什么事?华为日历带你“穿越”涨知识

探寻过去就会发现各种有趣的历史故事和知识值得细细品味,如果你想“穿越”过去,回顾历史上的今天曾经发生过的事件,或是以更轻松的方式增长历史知识,不妨试试订阅华为日历【历史上的今天】订阅服务。 无论是对历史一知半解的小白&…

基于PyQt5的桌面图像调试仿真平台开发(8)锐化

系列文章目录 基于PyQt5的桌面图像调试仿真平台开发(1)环境搭建 基于PyQt5的桌面图像调试仿真平台开发(2)UI设计和控件绑定 基于PyQt5的桌面图像调试仿真平台开发(3)黑电平处理 基于PyQt5的桌面图像调试仿真平台开发(4)白平衡处理 基于PyQt5的桌面图像调试仿真平台开发(5)…

CTFSHOW 每周大挑战 RCE极限挑战

RCE挑战1 开题直接给了源码 过滤了括号和点号。 使用内敛绕过。 payload: codeecho tac /f1agaaa;RCE挑战2 源码直接给了。 基本把能用的都过滤了,只剩下$()_;[],./字符,自增RCE无疑。 //相当于 ($_GET[_])($_GET[__]) 使用的时候url编…

基于simulink使用二维规范化互相关进行模式匹配和目标跟踪(附源码)

一、前言 此示例演示如何使用二维规范化互相关进行模式匹配和目标跟踪。双击“编辑参数”块以选择要检测的类似目标的数量。您还可以更改金字塔因子。通过增加它,您可以更快地将目标模板与每个视频帧匹配。更改金字塔因子可能需要更改阈值。 此外,还可…