Linux小黑板(10):信号

我们写在linux系统环境下写一个程序,唔,"它的功能是每隔1s向屏幕打印'hello world'。"

这时,我们在键盘上按出"Ctrl + C"后,进程会发生什么??

我们清晰地看到,进程已经在我们按出"Ctrl + C"后,进程退出了。那为什么会出现这个现象呢??是什么引发了当前运行的前台进程退出呢?
那么我们也就不卖关子了,"Ctrl +C"是一个组合键,作用就是向当前进程发送2号信号。
那么什么是信号呢?信号是如何产生的呢?进程收到信号后的处理动作又是什么呢?
-----前言
一、认识信号
我们在日常生活中,时常都会与信号打交道。例如,在学校听到铃声,在公路上看到红绿灯,但是如果我们从没有上过学,或者从没有去过公路,我们压根不知道出现眼前这种情况,我们的对应动作是什么。因此,我们对信号的认识在于,"识别信号,行为产生",不仅仅是在于能够看到,能够知道这种情况下,是给我是遇到信号了,并且我还需要知道学校铃声响起,我就该上课或者下课了,红灯亮起,此时就不应该在将脚迈上公路。
为什么进程需要信号呢?
我们从识别信号到行为产生,首先就需要有人告诉你这是什么信号,面对这样的信号你要做出的行为是什么?"这是红绿灯","绿灯行红灯停"。唔,这很符合当下,是你通过学习交通知识得出的,并且你会将其信号翻译成形如上述的形式(如果你仍持有人类该有的理性)。这总比让一位主持交通管理的执行员扯着嗓门、比划着让哪路上的行车停止,哪路上的行车启动的行为要方便很多……
当你使用"Ctrl + C"组合热键时,你如何知道该进程收到了什么样的信号呢?你说,是2号信号(你前文说过)。那如果是"Ctlr+Z"组合键呢?恐怕,你只会抓耳挠腮地喃喃信号此时并非很吃香,因为你并不认识该信号,也就更不会有行为的产生。由此,识别信号其实是有成本的。
进程识别信号的本质,与我们识别信号的行为是一致的—— "识别信号,行为产生"。
Linux中信号宏定义:
/usr/include/bits/signum.h

Linux中的信号集:
kill -l 查看
[1,31]:普通信号
[34,64]:实时信号

二、信号产生
(1)信号产生的方式
键盘发送:
在了解了什么是信号后,我们现如今把目光聚焦到信号是如何产生的问题上来。例如,前文常提的两个组合键 "Ctlr +C" , "Ctrl + Z",Linux命令行就会从键盘上获取这两个组合键,并把它们解释为信号,发送给当前进程。

硬件异常:
我们举例一个除0操作的错误代码,并且用核心转储查看。
core-file + 形成的核心转储的文件

我们知道,该进程执行除0操作时收到了信号8。
如何理解除0错误?

如何理解未初始化指针解引用?
我们对一个未完成赋值指针进行解引用。


软件条件:
系统库中提供一个alarm函数,意为"闹铃"。即,过段时间就会给该进发送14闹铃信号。

程序运行3s后,进程收到alarm信号后退出。

当然软件条件还有管道,例如读端已经关闭,写端一直在写,OS绝不会允许这样浪费资源,因此会向正在运行的写端发送管道信号(SIGPIPE)。

系统调用:
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
当然,我们仍然可以通过系统调用向该进发送信号。这个kill函数你是否见着它很熟悉??这不就是我们在命令行输入的kill + signum + pid嘛? 是的! 命令行解释器的底层就是去调用的这个函数!

三、信号保存与阻塞
前文讲述了信号是如何发送的,信号是如何产生的条件。但事实上,信号产生后,只有接收方接收到了,才能进行之后的"递达",也就是行为产生。因此,当OS向进程发送信号时,该进程怎么知道OS向它发送了信号?OS发送了什么信号呢?
又比如,现在你叫张三,你很不喜欢讲台上的老师,于是乎,你根本不在乎他说什么。那么他"发出的任何信号",都不会被你识别,更别说"递达",即行为产生。由此,如果进程选择不接收OS发送的信号,又该作何处理??
信号相关概念:
1.实际执行信号的动作称为:信号抵达。
2.信号从产生到递达之间的状态:信号未决。
3.进程可以选择阻塞某个信号。
4.被阻塞的信号产生时将保持在未决状态,直到进程解除对此信号的阻塞,才执行递达的动作。
注意:
阻塞和忽略是不同的,只要信号被阻塞就不会递达,而忽略是在递达之后可选的一种处理动作
信号在内核中的表示:
block: 表示阻塞信号集
pending: 表示接收信号集
handler: 信号集方法

正如前文所述,linux内核中,信号num是一堆宏定义整数。
block、pending集是被设计成一种位图的数据结构!举个unsigend_int的例子,32个比特位表示信号个数可以是[1,32]。0表示阻塞(未接收)信号,1表示未阻塞(接收)信号。每一个pending集的比特位,都与handlers这个数组下标的位置一一对应。handlers数组是一个函数指针数组,里面存放的是每一种信号接收时,行为产生函数的地址。
所以,如果你想要改变一个信号,对应的默认行为,你就只需要将你实现的handlers方法函数的地址,填入到内核数据结构中handlers数组里即可。
四、信号处理
根据前文认识了什么是信号,以及信号的产生,我们可以得出如下的结论:
信号是发给进程的,信号产生于操作系统。
可是,我现在的问题是,当前进程收到信号后,就必须要放下"手头"的事,立马去处理到来的信号嘛?毕竟,当我妈叫现在我吃饭,这是一个信号,但是我现在正在写博客、正在上网课,我可以选择继续写我的博客,继续上我的课,当然我也可以选择立即直接扔掉手中敲打的键盘,也可以立即将那喋喋不休的腾讯会议结束掉,立刻前去吃饭。
由此,我们对于信号的处理似乎有,唔大概三种处理方式:
默认行为、忽视行为、自定义行为。

但是,我妈叫我吃饭了,我们是选择了继续干完当前的事,但是干完这些事之后,我才会去吃饭。因此,接收信号后,并不代表一定要产生行为,可以将它先保存,并在适合的时候进行处理。
那么什么算是合适的适合呢??
这里也不卖关子,内核态返回用户态的时候(这个之后会细谈)!
五、内核态vs用户态
我们知道了信号是发送给进程的,发送方是OS。但是OS是如何发送信号的?我们接收到信号时,该进程是怎么知道的?一定需要到进程的内核数据结构中去,但是我们能去吗?肯定不行!这个行为,只有OS才能帮我们这样做。同样,如果我们需要自定义信号捕捉(信号递达),不是我们去更改那个handler表,因为我们并没有权限!OS不信任任何人!
(1)身份切换

(2)内核地址空间
我们使用库函数时,只区分动态库和静态库。动态库的函数地址会在程序运行时加载进共享区,而使用静态库函数时,函数地址会被编译进源程序中,存储在代码区。
那么我们使用系统调用接口,我们是怎么找到它们的地址并,调用它们的?

总结:
信号产生:

信号抵达:

本篇到此结束,感谢你的阅读。
祝你好运,向阳而生~
相关文章:
Linux小黑板(10):信号
我们写在linux系统环境下写一个程序,唔,"它的功能是每隔1s向屏幕打印hello world。"这时,我们在键盘上按出"Ctrl C"后,进程会发生什么??我们清晰地看到,进程已经在我们按出"Ctrl…...
GO 语言基础语法一 (快速入门 Go 语言)
Go语言基础语法一. golang 标识符,关键字,命名规则二. golang 变量三. golang 常量四. golang 数据类型五. golang 布尔类型六. golang 数字类型七. golang 字符串1. go语言字符串字面量2. go语言字符串连接(1). 使用加号(2). 使用 fmt.Sprintf() 函数(3…...
Java高效率复习-SpringMVC[SpringMVC-2]
SpringMVC获取请求参数 SpringMVC获取请求参数的两种方式↓ 通过ServletAPI获取请求参数 将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象 通过request的API——getParameter(String s)方法来获取…...
【前端】一个更底层库-React基础知识点
目录Reat是什么?为什么要使用React类库比较容易学习,API非常少。组件内聚,容易组合原生组件和自定义组件融合渲染状态/属性驱动全局更新commonjs生态圈/工具栏完善React基础知识JSX概述JSX嵌入变量Event事件组合组合CHILDREN总结大家好&#…...
C++ 之枚举类型
文章目录参考描述枚举类型枚举类型枚举变量的声明及定义细节枚举常量的默认初始值枚举常量不可被修改赋值运算枚举常量与数据类型为枚举常量指定数据类型可选择的数据类型特殊的 Bool强枚举类型命名冲突强枚举类型参考 项目描述菜鸟教程C 枚举类型详解精通C (第九版…...
软件测试用例(3)
按照测试对象划分: 一)界面测试: 1)软件只是一种工具,软件和人的信息交流是通过界面来进行的,界面是软件和用户交流的最直接的一层,界面的设计决定了用户对于我们设计软件的第一映像,界面如同人的面孔,具有最吸引用户的…...
Spring——Bean管理-注解方式进行属性注入
Spring针对Bean管理中创建对象提供的注解有哪些?Component:普通Service:业务逻辑层Controller:controller层Repository:dao层用注解的方式是为什么?简化xml方式开发,只需要注解就可以完成在配置…...
【设计模式之美 设计原则与思想:设计原则】20 | 理论六:我为何说KISS、YAGNI原则看似简单,却经常被用错?
上几节课中,我们学习了经典的 SOLID 原则。今天,我们讲两个设计原则:KISS 原则和 YAGNI 原则。其中,KISS 原则比较经典,耳熟能详,但 YAGNI 你可能没怎么听过,不过它理解起来也不难。 理解这两个…...
Java代码弱点与修复之——Copy-paste error(复制粘贴错误)
弱点描述 Copy-paste error,复制粘贴错误。 是指在复制和粘贴代码时产生的错误。这种错误通常是由于程序员在复制代码时未正确编辑所复制的代码或编辑复制后的代码时忘记更改一些值或参数而导致的。复制粘贴错误可能会导致程序逻辑错误、编译错误或运行时错误。 示例代码 …...
Editor.md 的使用方法及图片处理
目录1. 资源下载2. 生成页面2.1 编辑和预览页面2.2 文本渲染页面3. 图片上传3.1 前端配置3.2 后端接口4. 图片粘贴[^2]1. 资源下载 官网下载 gitee 下载 2. 生成页面 2.1 编辑和预览页面 将资源(精简后 Editor.md 资源1)导入项目: 按照官…...
剑指 Offer II 018. 有效的回文
题目链接 剑指 Offer II 018. 有效的回文 easy 题目描述 给定一个字符串 s,验证 s是否是 回文串 ,只考虑字母和数字字符,可以忽略字母的大小写。 本题中,将空字符串定义为有效的 回文串 。 示例 1: 输入: s “A man, a plan, …...
Elasticsearch分析器(Analyzer)
Elasticsearch分析器(Analyzer) 文章目录Elasticsearch分析器(Analyzer)分析器概念内置分析器(8.6版本)自定义分析器elasticsearch-analysis-ik(简称ik,💕14.8kÿ…...
P6入门:了解P6 Professional 工具栏及地图分享
目录 引言 相关分享 引言 凭借更大的灵活性和增强的自定义功能,最新版本的 Oracle Primavera P6 Professional 的界面比早期版本有了巨大改进。对于有经验的伙伴来说,它仍然是熟悉的领域,几乎所有预期的功能都显示在前面。该界面可以更好地…...
习题30 if elif else 语句
people 30#变量people赋值30 cars 40#变量cars赋值40 buses 15#变量buses赋值 if cars > people:#如果出租车比人多print("We should take the cars")#我们坐出租车 elif cars < people:#elif后面必须跟条件,print("We should not take the…...
32 openEuler使用LVM管理硬盘-管理卷组
文章目录32 openEuler使用LVM管理硬盘-管理卷组32.1 创建卷组32.2 查看卷组32.3 修改卷组属性32.4 扩展卷组32.5 收缩卷组32.6 删除卷组32 openEuler使用LVM管理硬盘-管理卷组 32.1 创建卷组 可在root权限下通过vgcreate命令创建卷组。 vgcreate [option] vgname pvname ...…...
Jackson CVE-2017-17485 反序列化漏洞
0x00 前言 同CVE-2017-15095一样,是CVE-2017-7525黑名单绕过的漏洞,主要还是看一下绕过的调用链利用方式。 可以先看: Jackson 反序列化漏洞原理 或者直接看总结也可以: Jackson总结 涉及版本:2.8.10和2.9.x至2.…...
十大排序(C++版)
测试排序的题目: 912. 排序数组 - 力扣(LeetCode) 堕落的做法: class Solution { public:vector<int> sortArray(vector<int>& nums) {sort(nums.begin(),nums.end());return nums;} };视频推荐: …...
SpringMVC中的常用注解
Java知识点总结:想看的可以从这里进入 目录3.2、常用的注解3.2、常用的注解 Controller:代表此类是一个控制器,需要配置包的扫描。Spring MVC 是通过组件扫描机制查找应用中的控制器类的 在Spring6.0之后要求控制层必须添加该注解才会被识别成…...
English Learning - L2-3 英音地道语音语调 小元音 [ʌ] [ɒ] [ʊ] [ɪ] [ə] [e] 2023.02.27 周一
English Learning - L2-3 英音地道语音语调 小元音 [ʌ] [ɒ] [ʊ] [ɪ] [ə] [e] 2023.02.27 周一课前活动练习方法大小元音总结小元音准备工作[ʌ] 中元音发音技巧对应单词的发音对应句子的发音常见的字母组合[ɒ] 后元音发音技巧对应单词的发音对应句子的发音常见的字母组合…...
fastadmin后台登录页修改
直接替换就行 <!DOCTYPE html> <html lang"{$config.language}"> <head>{include file"common/meta" /}<style type"text/css">body {color: #999;background-color: #f1f4fd;background-size: cover;}a {color: #444;…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
【java】【服务器】线程上下文丢失 是指什么
目录 ■前言 ■正文开始 线程上下文的核心组成部分 为什么会出现上下文丢失? 直观示例说明 为什么上下文如此重要? 解决上下文丢失的关键 总结 ■如果我想在servlet中使用线程,代码应该如何实现 推荐方案:使用 ManagedE…...
智能体革命:企业如何构建自主决策的AI代理?
OpenAI智能代理构建实用指南详解 随着大型语言模型(LLM)在推理、多模态理解和工具调用能力上的进步,智能代理(Agents)成为自动化领域的新突破。与传统软件仅帮助用户自动化流程不同,智能代理能够自主执行工…...
Linux系统:进程间通信-匿名与命名管道
本节重点 匿名管道的概念与原理匿名管道的创建命名管道的概念与原理命名管道的创建两者的差异与联系命名管道实现EchoServer 一、管道 管道(Pipe)是一种进程间通信(IPC, Inter-Process Communication)机制,用于在不…...
rk3506上移植lvgl应用
本文档介绍如何在开发板上运行以及移植LVGL。 1. 移植准备 硬件环境:开发板及其配套屏幕 开发板镜像 主机环境:Ubuntu 22.04.5 2. LVGL启动 出厂系统默认配置了 LVGL,并且上电之后默认会启动 一个LVGL应用 。 LVGL 的启动脚本为/etc/init.d/pre_init/S00-lv_demo,…...
SAP学习笔记 - 开发24 - 前端Fiori开发 Filtering(过滤器),Sorting and Grouping(排序和分组)
上一章讲了SAP Fiori开发的表达式绑定,自定义格式化等内容。 SAP学习笔记 - 开发23 - 前端Fiori开发 Expression Binding(表达式绑定),Custom Formatters(自定义格式化)-CSDN博客 本章继续讲SAP Fiori开发…...
