Linux:信号的概念与产生
信号概念
信号是进程之间事件异步通知的一种方式
在Linux命令行中,我们可以通过ctrl + c来终止一个前台运行的进程,其实这就是一个发送信号的行为。我们按下ctrl + c是在shell进程中,而被终止的进程,是在前台运行的另外一个进程。因此信号是一种进程之间的通知方式。
可以通过指令kill -l来查询信号:
以上就是Linux中的全部信号,它们分为两个区间:[1, 31] 和[34, 64],也就是说没有0,32,33这三个信号,虽然信号的最大编号为64,但实际上只有62个信号。
[1, 31]:这些信号称为非实时信号,当进程收到这些信号后,可以自己选择合适的时候处理[34, 64]:这些信号称为实时信号,当进程收到这些信号后,必须立马处理
由于现在的操作系统基本都是分时操作系统,因此实时信号其实是不符合设计理念的,几乎用不到实时信号,本博客只讲解非实时信号。
所有信号都是大写的单词,在C/C++中,一般来说宏就是大写的,其实信号名就是宏。
那么进程收到信号后要怎么处理呢?
进程有三种处理信号的方式:
- 忽略此信号
- 执行信号的默认处理函数
- 执行信号的自定义处理函数,这种方式也称为
信号捕捉
其中Term,Ign,Core,Stop,Cont就是信号处理的默认行为
Term:默认操作是终止进程Ign:默认操作是忽略信号Core:默认操作是终止进程并转储核心Stop:默认操作是暂停进程Cont:默认操作是,如果该进程当前已暂停,则继续该进程
signal函数,包含在头文件<signal.h>中,可以自定义信号的处理方式,函数原型如下:
sighandler_t signal(int signum, sighandler_t handler);
其中这个sighandler_t类型,本质是一个void (*)(int)类型的函数指针,也就是说自定义的信号处理函数必须是void (int)的格式。其中这个处理函数的第一个参数int,就是用来接收信号的编号的。
而返回值也是sighandler_t,其返回原先该信号处理的函数的函数指针。
void handler(int sig)
{cout << "get sig: " << sig << endl;
}int main()
{signal(2, handler);while(true){cout << "hello world!" << endl;sleep(1);}return 0;
}
以上代码中,我们通过signal(2, handler);把2号信号的处理方式变成了执行函数handler,此后进程收到2 号信号时,就会执行cout << "get sig: " << sig << endl;了。
而2号信号SIGINT就是ctrl + C发送的信号,因此我们可以直接在shell中通过ctrl + C来发送2号信号,从而验证效果。
信号产生
简单讲解了一下信号的三种处理方式后,再来看看信号是如何产生的,在Linux中,信号主要有两种产生方式:软件条件,硬件异常。
软件信号
在 Linux 中,“软件条件” 发出的信号指的是由 进程自身或其他进程 产生的信号,而不是由硬件中断或其他外部事件触发的信号。
Linux中有多种系统调用可以发送信号,在此我讲解kill,raise,abort,alarm四种接口,其中abort并不是一个系统调用,而是一个用户操作接口。
kill
kill函数用于给指定pid的进程发送指定信号,需要头文件<sys/types.h>和<signal.h>,函数原型如下:
int kill(pid_t pid, int sig);
参数:
pid:收到该信号的进程的pidsig:发送哪一个信号
返回值:
- 返回
0:发送信号成功 - 返回
-1:发送信号失败
void handler (int sig)
{cout << "get sig: " << sig << endl;exit(1);
}int main()
{pid_t id = fork();if (id == 0) // 子进程{signal(2, handler);while (true){cout << "I am child process" << endl;sleep(1);}}sleep(5);kill(id, 2);return 0;
}
以上示例中,父进程通过fork创建子进程,sleep五秒后通过kill(id, 2);给子进程发送(2) SIGINT信号。子进程通过signal(2, handler);修改了信号处理方式,随后每秒钟输出一次I am child process。
在handler中,会先输出get sig: 2,表示自己收到了信号,然后exit退出进程。
另外的,也可以通过kill指令发送信号,格式为:
kill -sig pid
其中sig为要发送的信号,pid为收到信号的进程pid。
其实kill指令底层就是调用kill接口,依然属于系统调用的范围。
raise
raise函数用于给自己发送信号,需要头文件<signal.h>,函数原型如下:
int raise(int sig);
参数:
sig:发送哪一个信号
返回值:
- 返回
0:发送信号成功 - 返回
-1:发送信号失败
void handler(int sig)
{cout << "get sig: " << sig << endl;exit(1);
}int main()
{signal(2, handler);int cnt = 5;while (cnt){cout << "I am a process cnt = " << cnt-- << endl;sleep(1);}raise(2);return 0;
}
先通过signal(2, handler);修改信号的处理函数,随后循环五次,输出"I am a process cnt = ",最后通过raise(2);给自己发送(2) SIGINT信号。
abort
abort函数用于给自己发送(6) SIGABRT信号,需要头文件<stdlib.h>,属于用户操作接口,函数原型如下:
void abort(void);
这个函数功能十分简单,就是给自己发送(6) SIGABRT信号,示例:
int main()
{abort();return 0;
}
输出结果:
Aborted
最后进程输出了Aborted表示自己收到了(6) SIGABRT信号。
alarm
alarm函数用于设定一个闹钟,在一定之间后给当前进程发送信号(14) SIGALRM,需要头文件<unistd.h>,函数原型如下:
unsigned int alarm(unsigned int seconds);
参数:
seconds:在seconds秒后发送信号
返回值:
- 如果之前有还没响的闹钟:取消上一次的闹钟,并返回上一次闹钟的剩余秒数
- 如果之前没有闹钟了:返回
0
void handler(int sig)
{cout << "get sig: " << sig << endl;exit(1);
}int main()
{signal(SIGALRM, handler);alarm(1);int i = 0;while(true){cout << i++ << endl;}return 0;
}
以上代码中,先通过signal(SIGALRM, handler);自定义信号(14) SIGALRM的处理方式。然后通过alarm(1);设定一秒钟的闹钟,在一秒内,程序会不断执行while循环让i++,我们可以看看一秒内计算机可以执行多少次i++。
输出结果:
74560
get sig:14
可以看到,计算到74560时,就收到了SIGALRM,终止进程了。
硬件信号
硬件信号指的是由 硬件事件 触发的信号,而不是由软件代码逻辑控制的。
具体来说,以下情况属于硬件条件发出的信号:
- 中断: 硬件设备,例如键盘、鼠标、网络接口等,在发生事件时会向 CPU 发送中断信号,例如键盘按键按下、网络数据包到达等。
- 异常: CPU 在执行指令过程中,如果遇到错误情况,例如除以零、内存访问错误等,会产生异常信号。
- 时钟中断: 系统定时器会定期向 CPU 发送时钟中断信号,用于调度进程和执行定时任务。
键盘产生信号
通过键盘发送信号是最简单的信号发送方式,最常用的有ctrl + C和ctrl + \。
ctrl + C:向前台进程发送(2) SIGINT信号,效果为直接终止进程ctrl + \:向前台进程发送(3) SIGQUIT信号,效果为直接终止进程
硬件中断
硬件给进程发送信号的本质,其实是通过硬件中断。
硬件中断是指硬件设备向 CPU 发送的信号,通知 CPU 有事件发生需要处理。当一个硬件设备需要向 CPU 汇报事件发生时,它会向 CPU 发送一个中断信号。CPU 接收这个信号后,会暂停当前执行的任务,转而去处理硬件设备的请求。
int main()
{int a = 5 / 0;return 0;
}
这是一个很经典的除零错误,如果我们强行运行这个进程,会报出错误Floating point exception,本质上是收到了信号(8) SIGFPE,其实本质上是发生了硬件中断。 
CPU:CPU是一个硬件,其要处理计算,而5/0这个计算过程就是在CPU中完成的,当CPU检测到这个计算中0做了除数,于是对自己发起硬件中断操作系统:操作系统检测到硬件中断后,跳转到中断处理程序(中断处理程序是Linux内核的一部分),然后检测该硬件中断是什么原因,发现是因为除零错误,于是给进程发送(8) SIGPFE信号进程:进程收到操作系统发来的(8) SIGPFE信号后,执行相应的处理措施
我们之前的ctrl + C按键发送(2) SIGINT信号,本质也是硬件中断,当我们从键盘输入了数据后,键盘向CPU发出硬件中断,随后CPU去执行操作系统中的硬件中断程序,发现是用户按下了ctrl + C,于是操作系统向进程发送(2) SIGINT信号。
与软件条件信号相比,硬件条件信号具有以下特点:
- 由硬件触发: 硬件条件信号的产生是由硬件事件触发的,而不是由代码逻辑决定的
- 不可控性: 硬件条件信号的产生通常无法被进程控制,例如硬件设备的故障、网络连接中断等。
- 不可预测性: 硬件条件信号的产生通常是不可预测的,因为它们是由硬件事件触发的。
相关文章:
Linux:信号的概念与产生
信号概念 信号是进程之间事件异步通知的一种方式 在Linux命令行中,我们可以通过ctrl c来终止一个前台运行的进程,其实这就是一个发送信号的行为。我们按下ctrl c是在shell进程中,而被终止的进程,是在前台运行的另外一个进程。因…...
云监控(华为) | 实训学习day2(10)
spring boot基于框架的实现 简单应用 - 用户数据显示 开发步骤 第一步:文件-----》新建---项目 第二步:弹出的对话框中,左侧选择maven,右侧不选任何内容. 第三步,选择maven后,下一步 第4步 :出现对话框中填写项目名称 第5步&…...
数据结构第35节 性能优化 算法的选择
算法的选择对于优化程序性能至关重要。不同的算法在时间复杂度、空间复杂度以及适用场景上有着明显的差异。下面我将结合具体的代码示例,来讲解几种常见的算法选择及其优化方法。 示例 1: 排序算法 场景描述: 假设我们需要对一个整数数组进行排序。 算法选择: …...
每天一个数据分析题(四百三十六)- 正态分布
X为服从正态分布的随机变量N(2, 9), 如果P(X>c)P(X<c), 则c的值为() A. 3 B. 2 C. 9 D. 2/3 数据分析认证考试介绍:点击进入 题目来源于CDA模拟题库 点击此处获取答案 数据分析专项练习题库 内容涵盖Python,SQL&…...
跟我学C++中级篇——虚函数的性能
一、虚函数性能 一般来说,面向对象的设计中,继承和多态是其中两个非常重要的特征。从使用的过程来看,一般应用到继承的,使用多态的可能性就非常大。而多态的实现有很多种, 但开发者通常认为的多态(动多态&…...
trl - 微调、对齐大模型的全栈工具
文章目录 一、关于 TRL亮点 二、安装1、Python包2、从源码安装3、存储库 三、命令行界面(CLI)四、如何使用1、SFTTrainer2、RewardTrainer3、PPOTrainer4、DPOTrainer 五、其它开发 & 贡献参考文献最近策略优化 PPO直接偏好优化 DPO 一、关于 TRL T…...
GuLi商城-商品服务-API-品牌管理-品牌分类关联与级联更新
先配置mybatis分页: 品牌管理增加模糊查询: 品牌管理关联分类: 一个品牌可以有多个分类 一个分类也可以有多个品牌 多对多的关系,用中间表 涉及的类: 方法都比较简单,就不贴代码了...
【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会
【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会 【创作不易,求点赞关注收藏】 文章目录 【linux】服务器ubuntu安装cuda11.0、cuDNN教程,简单易懂,包教包会一、版本情况介绍二、安装cuda1、到官网…...
在 Apifox 中如何高效批量添加接口请求 Body 参数?
在使用 Apifox 进行 API 设计时,你可能会遇到需要添加大量请求参数的情况。想象一下,如果一个接口需要几十甚至上百个参数,若要在接口的「修改文档」里一个个手动添加这些参数,那未免也太麻烦了,耗时且易出错。这时候&…...
专业PDF编辑工具:Acrobat Pro DC 2024.002.20933绿色版,提升你的工作效率!
软件介绍 Adobe Acrobat Pro DC 2024绿色便携版是一款功能强大的PDF编辑和转换软件,由Adobe公司推出。它是Acrobat XI系列的后续产品,提供了全新的用户界面和增强功能。用户可以借助这款软件将纸质文件转换为可编辑的电子文件,便于传输、签署…...
车载音视频App框架设计
简介 统一播放器提供媒体播放一致性的交互和视觉体验,减少各个媒体应用和场景独自开发的重复工作量,实现媒体播放链路的一致性,减少碎片化的Bug。本文面向应用开发者介绍如何快速接入媒体播放器。 主要功能: 新设计的统一播放U…...
StarRocks on AWS Graviton3,实现 50% 以上性价比提升
在数据时代,企业拥有前所未有的大量数据资产,但如何从海量数据中发掘价值成为挑战。数据分析凭借强大的分析能力,可从不同维度挖掘数据中蕴含的见解和规律,为企业战略决策提供依据。数据分析在营销、风险管控、产品优化等领域发挥…...
VUE中setup()
在Vue中,setup() 函数是Vue 3.0及更高版本引入的一个重要特性,它是Composition API的入口点。setup() 函数用于初始化组件的状态和逻辑,包括定义响应式数据、方法和生命周期钩子。以下是关于setup() 函数的详细解释: 1. 作用与特…...
【单元测试】SpringBoot
【单元测试】SpringBoot 1. 为什么单元测试很重要?‼️ 从前,有一个名叫小明的程序员,他非常聪明,但有一个致命的缺点:懒惰。小明的代码写得又快又好,但他总觉得单元测试是一件麻烦事,觉得代码…...
分布式搜索引擎ES-elasticsearch入门
1.分布式搜索引擎:luceneVS Solr VS Elasticsearch 什么是分布式搜索引擎 搜索引擎:数据源:数据库或者爬虫资源 分布式存储与搜索:多个节点组成的服务,提高扩展性(扩展成集群) 使用搜索引擎为搜索提供服务。可以从海量…...
TCP三次握手与四次挥手详解
1.什么是TCP TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的通信协议,属于互联网协议族(TCP/IP)的一部分。TCP 提供可靠的、顺序的、无差错的数据传输服务&…...
【Windows】操作系统之任务管理器(第一篇)
一、操作系统简介 Windows操作系统是由微软公司(Microsoft)开发的一款图形操作系统,它以其强大的功能和广泛的用户基础,成为了目前世界上用户使用最多、兼容性最强的操作系统之一。以下是关于Windows操作系统的详细介绍ÿ…...
图同构的必要条件
来源:离散数学...
Django获取request请求中的参数
支持 post put json_str request.body # 属性获取最原始的请求体数据 json_dict json.loads(json_str)# 将原始数据转成字典格式 json_dict.get("key", "默认值") # 获取数据参考 https://blog.csdn.net/user_san/article/details/109654028...
kotlin compose 实现应用内多语言切换(不重新打开App)
1. 示例图 2.具体实现 如何实现上述示例,且不需要重新打开App ①自定义 MainApplication 实现 Application ,定义两个变量: class MainApplication : Application() { object GlobalDpData { var language: String = "" var defaultLanguage: Strin…...
网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
初探Service服务发现机制
1.Service简介 Service是将运行在一组Pod上的应用程序发布为网络服务的抽象方法。 主要功能:服务发现和负载均衡。 Service类型的包括ClusterIP类型、NodePort类型、LoadBalancer类型、ExternalName类型 2.Endpoints简介 Endpoints是一种Kubernetes资源…...
毫米波雷达基础理论(3D+4D)
3D、4D毫米波雷达基础知识及厂商选型 PreView : https://mp.weixin.qq.com/s/bQkju4r6med7I3TBGJI_bQ 1. FMCW毫米波雷达基础知识 主要参考博文: 一文入门汽车毫米波雷达基本原理 :https://mp.weixin.qq.com/s/_EN7A5lKcz2Eh8dLnjE19w 毫米波雷达基础…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践
01技术背景与业务挑战 某短视频点播企业深耕国内用户市场,但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大,传统架构已较难满足当前企业发展的需求,企业面临着三重挑战: ① 业务:国内用户访问海外服…...
链式法则中 复合函数的推导路径 多变量“信息传递路径”
非常好,我们将之前关于偏导数链式法则中不能“约掉”偏导符号的问题,统一使用 二重复合函数: z f ( u ( x , y ) , v ( x , y ) ) \boxed{z f(u(x,y),\ v(x,y))} zf(u(x,y), v(x,y)) 来全面说明。我们会展示其全微分形式(偏导…...
