Linux——信号概念与信号产生方式
目录
一、概念
二、前台进程与后台进程
1.ctrl+c
2.ctrl+z
三、信号的产生方式
1.键盘输入产生信号
2.系统调用发送信号
2.1 kill()函数
2.2 raise()函数
2.3 abort()函数
3.异常导致信号产生
3.1 除0异常
3.2 段错误异常
4.软件条件产生信号
4.1 管道
4.2 闹钟
四、核心转储
总结
一、概念
生活中,我们也经常遇到信号,比如早八的闹钟、红绿灯、鲁大师在电脑里面抽烟、周杰伦的到底有谁知道~是几点的方向~你~才~会~收~到~暗~号~。在信号还没有产生的时候,我们已经知道什么样的信号需要如何去处理,比如早八的闹钟,在闹钟响之前,我们就知道早上要么起床去上课,要么把闹钟一关继续睡觉。
信号产生了,我们不一定要立即处理他,而是在合适的时候处理。比如你肚子疼,需要拉肚子,但是游戏已经开了,对抗路已经在操作了,今天不管,你有本事就拉裤兜,必须先把这把打完再去。因此我们要对信号进行暂时保存。
同时,我们并不清楚具体什么时候肚子痛,因此信号到来相对于我现在正在打的游戏,是异步(多执行流同时进行操作)的。
小总结:
我们能识别信号,同时知道该如何处理
信号是异步的
可以对信号进行暂时保存
在合适的时候处理信号
信号是向目标进程发送消息通知的一种机制。
二、前台进程与后台进程
1.ctrl+c
进程在运行时,一般都是前台进程,如下代码,./mytest运行起来,我们输入命令没用反应,但我们运行时输入ctrl+c可以终止掉进程。
如果我们执行的时候在后面加上 & ,就让进程在后台运行,此时输入命令可以反应,但是进程不能被ctrl+c终止。
这是因为前台进程只能有一个,后台进程可以有多个,由于shell也是一个进程,因此当进程在前台运行时,shell需要退入到后台进程中去,因此无法接受指令。而你现在输入ctrl+c终止进程,就是让前台进程终止,自然进程就结束了。
而当你进程以后台方式启动时,前台进程是shell,因此输入指令可以有结果,如果你输入ctrl+c,shell自己会保护自己,无法被ctrl+c终止,后台进程并没有收到ctrl+c,因此无法终止后台进程。
之前我们提到,后台进程可以有多个,比如现在我们重定向到log1.txt与log2.txt,输入指令jobs可以看到后台进程的运行情况。
他们在后台运行,并不影响前台shell接受指令,同时ctrl+c也无法终止。
我们输入fg + number,就可以将后台进程提到前台来,输入ctrl+c就可以终止掉该进程了。
小总结:判断是前台进程还是后台进程,看shell有没有能力接受用户输入,有就是后台进程,没有就是前台进程。
2.ctrl+z
输入ctrl+z可以暂停前台进程,但是被暂停的进程会自动放到后台,也就是我输入指令命令行能接受了。
现在我们输入 bg+number ,就可以将暂停的后台进程继续运行。
小总结:
- ./mytest & 让进程在后台运行
- jobs 查看后台进程
- fg + number 将后台进程放到前台
- ctrl+z 暂停前台进程并放到后台
- bg + number 将暂停的后台进程继续执行
三、信号的产生方式
1.键盘输入产生信号
在上面,我们学习ctrl+c终止前台进程,其实ctrl+c的本质上就是信号,他是信号表中的2号信号。
我们可以通过写代码的方式来查看该现象。
signal函数:能将收到的信号做自定义处理
- 参数1:信号num
- 参数2:返回值为void,参数为int的函数指针
#include<iostream>
#include<unistd.h>
#include<signal.h>using namespace std;void sighandler(int signo)
{cout<<"收到了"<<signo<<"号信号"<<endl;exit(1);
}int main()
{signal(2,sighandler);while(1){cout<<"pid: "<<getpid()<<endl;sleep(1);}
}
运行后发现,输入ctrl+c,会打印出内容,同时发送2号指令也会打印出相同的内容,由此可见,ctrl+c 等价于发送2号信号 。也就是键盘输入可以产生信号。
- 我们知其然,还要知其所以然。
- 我们在键盘中输入ctrl+c,会被操作系统接受到你的输入,因为操作系统是进程的管理者,他判断出你输入的内容是终止信号,同时是输入给当前运行的前台进程的。那么操作系统肯定需要告诉进程,信号到来了,你赶紧处理。
- 在进程的角度来看,进程一定要通过存储来表示自己是否收到信号,收到了哪种信号。这完全可以通过位图来实现,比特位的位置代表收到的哪种信号,比特为的内容0/1代表是否收到信号。由于普通信号只有1-31个,因此用32位的整形变量就可以判断了。
- 我们之前提到,在信号没有到来时,进程就已经知道该如何处理相关信号,因此进程还得有一张自己的函数指针数组,数组的下标与信号的编号相关,于是,当发现信号位图中有信号的到来,知道是哪一张信号,然后会调用信号相关的函数进行执行。
- 操作系统向目标进程发送信号,其实本质上是写信号,将该进程信号位图的相关位置设置为1
那么既然ctrl+c是一个信号,之前我们学过的ctrl+z,也应该是信号咯。当然没错,ctrl+z是20号信号SIGTSTP。还有ctrl+\,是3号信号
跟之前一样,使用signal捕获一下2号信号,3号信号,和20号信号。
9号信号不可被自定义捕捉,因为操作系统得有能力杀死任意进程,如果某个进程是恶意进程,一直在读取你的数据,或者对操作系统做破坏,那么该进程捕捉了所有信号,岂不是杀不掉了,因此操作系统设置9号信号不可被捕捉。
2.系统调用发送信号
2.1 kill()函数
有一个kill的系统调用函数,他可以往指定的进程发送指定信号。我们可以通过该函数来发送信号。
kill:给指定进程发送信号
- 参数1:进程pid
- 参数2:信号编号
代码如下
#include<iostream>
#include<unistd.h>
#include<signal.h>
#include<string>using namespace std;void Usage(const string& proc)
{cout<<"\n Usage: "<< proc <<" -signumber process"<<endl;
}int main(int argc,char* argv[])
{if(argc!=3){Usage(argv[0]);exit(0);}int signumber = stoi(argv[1]+1);int processpid = stoi(argv[2]);kill(processpid,signumber);
}
我们就可以利用kill函数,给他传信号与进程pid,即可将信号发送给此进程。
2.2 raise()函数
kill是给任意进程发送任意信号,而raise是给自己发送任意信号
kill:给指定进程发送信号
- 参数1:信号编号
使用很简单,如下,raise(2)代表给自己发送2号信号
因为我们自定义捕捉了,因此会一直收到2号信号。
2.3 abort()函数
给自己发送abort信号,是6号信号,参数返回值都不管,直接调用即可。
我们发现,进程确实收到了6号信号,我们sighandler里面并没有让进程退出,但是进程却被Aborted终止,这是abort函数的特点,就是进程收到6号信号,你可以自定义捕捉,但捕捉完毕我仍然会终止。
3.异常导致信号产生
C++我们学过异常,发生异常了,代码并不会再往后面执行,而是直接终止,除非你捕获了异常。
3.1 除0异常
如下代码,你发生了除0错误,编译的时候就会警告,当你执行的时候,告诉你浮点数异常。这是8号信号 SIGFPE。
我们将信号捕捉,运行,我们并没有写循环,按道理只会打印一次,这里发现进程在一直打印消息。
这是因为进程在运行的时候,会将进程中的数据放到CPU里面的寄存器去运行,现在CPU运算发现了除0错误,会给相应的标志位写上1,记录你的错误,操作系统就知道进程的错误了(因为操作系统是软硬件资源的管理者),那么操作系统需要发送对应信号干掉目标进程。
但是你自己的操作,将信号自定义捕捉了,杀死不了,而后进程就切换了,当进程又切换回来时,操作系统又发现你对应的标志位为1,因此又给你发送信号,从此往复,会一直发送信号,却又杀不掉你。
3.2 段错误异常
我们写C/C++代码的时候,经常会遇到段错误。比如野指针,越阶访问等等。段错误异常是11号信号SIGSEGV,因此我们捕捉11号信号看看结果。
跟之前一样,没有写循环,依然一直报错。这是在访问虚拟内存页表时,发现页表中没有对应内容虚拟到物理的映射。发生段错误,标志位设置,操作系统发送信号给进程,进程收到信号并自定义捕捉,进程切换,又回到该进程,发现标志位为1,继续发送信号,继续套娃。
4.软件条件产生信号
4.1 管道
我们之前在学习管道的时候,当我们把读端关闭的时候,写端会直接终止,因为操作系统给写端发送SIGPIPE信号,告诉写端,兄弟别舔了,她已经把你拉黑了。此时我们并没有涉及到寄存器或者其他硬件设备,虽说有内存,但是内存空间都是我自己开辟的呀,我自己的东西我爱咋用咋用,操作系统不会无缘无故给你发信号,这就叫软件条件。
4.2 闹钟
alarm:可以设置闹钟->给当前进程发送14号信号
参数:设置几秒中后的闹钟
返回值:正常返回0,闹钟提前返回剩余时间。
在5次打印后收到了消息,返回值为0。
综上,产生信号的方式有很多,但是发送信号只能由操作系统来完成!!!也就是向进程PCB中的信号位图写入。
四、核心转储
首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁 盘上,文件名通常是core,这叫做Core Dump。
命令行输入指令 man 7 signal ,往下翻可以查看信号的详细信息,这里可以看到信号的动作有Term、Core、Ign(ignore)、Cont(continue)、Stop。
其他的都比较好理解,比如Ign忽略,Cont继续,Stop暂停。但是还有Term和Core这两种,我们学过的信号这两种类型都有,他们都是终止进程,有什么区别呢?
我们发现Core中有SIGABRT、SIGFPE、SIGSEGV等等,他们都比较像异常情况。报错的具体代码尚不清楚。需要用户进一步排查
而Term中的SIGINT(键盘中断)、SIGKILL(杀死进程)等等,其实他们都没犯错, 只是被杀掉了。结果很清楚
你的代码如果出现了Core类型的错误,其实会发生core dump(核心转储),也就是在当前目录下多出一个以进程pid命名的 core.pid 文件。我们可以通过查看gbd查看代码具体报错位置信息。但是core dump功能是被默认关闭的。
输入指令ulimit -a可以查看系统的配置项,其中第一项core file size就是core dump,大小为0,我们可以将他大小设置一下
输入指令ulimit -c + size,就可以更改core file size 的大小,这是内存级别的,也就是重启xshell会自动恢复。
现在再更改代码并运行就会发现多了core dumped,发生了核心转储。
我们现在gdb调试mytest,同时在gdb中输入core-file + core.pid ,此时就可以看到该文件是在具体哪个地方出错。
总结
- 信号的产生,最终都要由操作系统来进行执行,这是因为操作系统是进程的管理者。
- 进程在信号到来不会立即处理,而是在合适的时候处理。
- 由于信号不会被立即处理,因此信号需要暂时被进程记录下来,记录在信号位图中。
- 信号在没有收到信号的时候,已经知道自己该如何处理信号。
- 操作系统向进程发送信号,本质是向目标进程的信号位图中写信号(置1)。
下一章:信号的保存与处理
相关文章:

Linux——信号概念与信号产生方式
目录 一、概念 二、前台进程与后台进程 1.ctrlc 2.ctrlz 三、信号的产生方式 1.键盘输入产生信号 2.系统调用发送信号 2.1 kill()函数 2.2 raise()函数 2.3 abort()函数 3.异常导致信号产生 3.1 除0异常 3.2 段错误异常 4.软件条件产生信号 4.1 管道 4.2 闹钟…...

赋值语句还能当判断条件?涨芝士了!
赋值和条件看似是C语言中毫不相关的两个概念,虽然实际过程中我猜测不会有太多这种不太符合常理的情况出现,但是现在在学习的过程中,为了出题而出题总是会整出一些花活出来.....这很难不让人联想起高中时一些大佬为了彰显自己的数学天赋而自己…...

数据结构 - 算法效率|时间复杂度|空间复杂度
目录 1.算法效率 2.时间复杂度 2.1定义 2.2大O渐近表示法 2.3常见时间复杂度计算举例 3.空间复杂度 3.1定义 3.2常见空间复杂度计算举例 1.算法效率 算法的效率常用算法复杂度来衡量,算法复杂度描述了算法在输入数据规模变化时,其运行时间和空间…...

接口自动化之 + Jenkins + Allure报告生成 + 企微消息通知推送
接口自动化之 Jenkins Allure报告生成 企微消息通知推送 在jenkins上部署好项目,构建成功后,希望可以把生成的报告,以及结果统计发送至企微。 效果图: 实现如下。 1、生成allure报告 a. 首先在Jenkins插件管理中&#x…...

『Apisix安全篇』探索Apache APISIX身份认证插件:从基础到实战
🚀『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 📣读完这篇文章里你能收获到 🛠️ 了解APISIX身份认证的重要性和基本概念,以及如何在微服务架构中实施API安全。🔑 学习如何使…...

【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了
【01-20】计算机网络基础知识(非常详细)从零基础入门到精通,看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用1、OSI 的七层模型分别是?各自的功能是什么?2、说一下一次完整的HTTP请求…...
『大模型笔记』常见的分布式并行策略(分布式训练)
常见的分布式并行策略(分布式训练) 文章目录 一. 为什么分布式训练越来越流行二. 常见的并行策略2.1 数据并行2.2 模型并行2.3 流水并行2.4 混合并行二. 参考文献一. 为什么分布式训练越来越流行 近年来,深度学习被广泛应用到各个领域,包括计算机视觉、语言理解、语音识别、广…...

java 企业工程管理系统软件源码+Spring Cloud + Spring Boot +二次开发+ 可定制化
工程项目管理软件是现代项目管理中不可或缺的工具,它能够帮助项目团队更高效地组织和协调工作。本文将介绍一款功能强大的工程项目管理软件,该软件采用先进的Vue、Uniapp、Layui等技术框架,涵盖了项目策划决策、规划设计、施工建设到竣工交付…...

3D数据格式导出工具HOOPS Publish如何生成高质量3D PDF?
在当今数字化时代,从建筑设计到制造业,从医学领域到电子游戏开发,3D技术已经成为了不可或缺的一部分。在这个进程中,将3D模型导出为3D PDF格式具有重要的意义。同时,HOOPS Publish作为一个领先的解决方案,为…...
【springboot】闲话 springboot 的几种异步机制 及 长轮询的概念和简单实现
文章目录 引子springboot的几种异步形式开启异步支持和线程池配置(重要)第一种:Async第二种:Callable<T>第三种:WebAsyncTask<T>第四种:DeferredResult<T> 长轮询的简单实现概念实现服务…...

Mysql---安全值守常用语句
文章目录 目录 文章目录 一.用户权限设置 用户设置 元数据查询 Union联合查询 分组查询 字符串函数 总结 一.用户权限设置 用户设置 #用户创建 create user "用户名""%主机名" identified by "密码" #用户删除 drop user 用户名 #用户查询…...
containerd快速安装指南
1 containerd快速安装指南🚀 本指南旨在提供一个简洁有效的方法来安装containerd。我们将通过一份易于理解的脚本步骤,指导您完成安装🔧。请根据您的实际需求,适当调整containerd版本及其相关依赖。 注意事项: 本安装…...
Javascript - 正则表达式相关的一些基础的范例
很久以前的一些学习资料,归档发布; 正则表达式的基础,以HTML代码来示范: <html><head><title></title><script language"javascript">function test(){//从页面要求客户输入一个字符串…...
JUC:线程活跃性(死锁、活锁、饥饿)
文章目录 线程活跃性死锁活锁解饿 线程活跃性 死锁 两个线程相互等待对方已拥有的锁,就会相互一直等待,不会停止。 t1拥有a锁,等待b锁。 t2拥有b锁,等待a锁。 Slf4j(topic "c.Test3") public class st3 {public st…...
RGB到灰度图像的转换原理及例程
RGB到灰度图像的转换是一种常用的图像处理操作,其原理是根据人眼对不同颜色的敏感度,将彩色图像的红、绿、蓝三个通道的像素值按照一定权重进行加权平均,得到灰度图像的像素值。 在RGB图像中,每个像素点由红、绿、蓝三个分量组成…...

PCA+DBO+DBSCN聚类,蜣螂优化算法DBO优化DBSCN聚类,适合学习,也适合发paper!
PCADBODBSCN聚类,蜣螂优化算法DBO优化DBSCN聚类,适合学习,也适合发paper! 一、蜣螂优化算法 摘要:受蜣螂滚球、跳舞、觅食、偷窃和繁殖等行为的启发,提出了一种新的基于种群的优化算法(Dung Beetle Optim…...
创建数据库与表单以及管理表单和数据
一、用于创建数据库的命令以及作用 命令作用CREATE DATABASE 数据库名称创建新的数据库DESCRIBE 表单名称描述表单UPDATE 表单名称SET attribute新值WHERE attribute>原始值更新表单中的数据USE 数据库名称指定使用的数据库SHOW databases显示当前已有的数据库SHOW tables显…...
Milvus+ATTU环境搭建
1.使用Docker Compose安装Milvus Standalone 下载安装单机版milvus向量数据库 https://milvus.io/docs/install_standalone-docker.md wget https://github.com/milvus-io/milvus/releases/download/v2.2.12/milvus-standalone-docker-compose.yml -O docker-compose.yml sud…...

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果
Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单实战案例 之八 简单水彩画效果 一、简单介绍 二、简单图像浮雕效果实现原理 三、简单水彩画效果案例实现简单步骤 四、注意事项…...

Chrome浏览器 安装Vue插件vue-devtools
前言 vue-devtools 是一个为 Vue.js 开发者设计的 Chrome 插件。它可以让你更轻松地审查和调试 Vue 应用程序。与普通的浏览器控制台工具不同,Vue.js devtools 专为 Vue 的响应性数据和组件结构量身定做。 1. 功能介绍 组件树浏览:这个功能可以让你查…...

第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版
7种色调职场工作汇报PPT,橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版:职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...
C语言中提供的第三方库之哈希表实现
一. 简介 前面一篇文章简单学习了C语言中第三方库(uthash库)提供对哈希表的操作,文章如下: C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...