讲师中心 微信公众号

工具推荐

视频效率加速
立刻MV
立刻MV

低成本歌曲 MV、视频生成

Laper
Laper

剧本策划到成片协作

AniShort
AniShort

AI短剧协同制作平台

Seko
Seko

AI短剧一键生成成片

【Linux】进程信号的产生

星强君_1026

星强君_1026

发布时间:2025-06-19 15:36:13

|

993人浏览过

|

来源于php中文网

原创

一、进程信号的概念

进程具备能够识别并处理信号的能力,这数据进程内置功能的一部分

当进程真正收到信号的时候,具备在合适的时候处理这个信号的能力

进程在信号产生到信号处理的这段时间有临时保存哪些信号已经发生了的能力

信号的处理方式有三种:默认动作、忽略、自定义动作

二、信号的产生1、常用的信号解析

我们常用的信号就是ctrl+c了,可以及时的把我们的前台进程(在Linux中,一个终端一般只有一个bash,每一次登陆只允许一个进程是前台进程,可以允许多个进程是后台进程)杀死,首先我们得到的结论是:ctrl+c的信号是被我们的前台进程接收到了

实际上,ctrl+c被进程解释成了2号信号,也就是SIGINT中断信号

【Linux】进程信号的产生

这张表中,前31个信号是普通信号,后31个信号是实时信号,其中没有32、33号信号,共62种信号

我们可以通过一些小办法来验证一下ctrl+c是2号信号: 我们前面说过信号的处理方式有三种:默认动作、忽略、自定义动作,我们按下ctrl+c前台程序中断这就属于默认动作,我们可以使用一个系统调用接口来捕捉信号,设置成我们自定义的动作,这个系统调用接口就是signal

代码语言:javascript代码运行次数:0运行复制
#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

返回值:成功返回之前该信号的处理函数指针,出错返回SIG_ERR signum:要处理的信号编号,参照上面的表 handler:函数指针,指向处理信号的函数,这是自定义动作,其中默认动作:SIG_DFL,忽略:SIG_IGN

【Linux】进程信号的产生
【Linux】进程信号的产生

信号被捕捉后“就不会让它逃跑了”,也就是说,信号捕捉后执行完sigint_handler函数就继续运行下面的while循环打印,此时只能通过kill -9杀死进程,当然也可以ctrl+z停止进程

【Linux】进程信号的产生

其中在所有信号中,9号信号SIGKILL和19号信号SIGSTOP是不可被捕捉的,他俩被捕捉了就没人能治的了进程了

2、从硬件到软件了解信号的产生

在现代操作系统中,为了保障系统的安全和稳定,采用了用户态和内核态的分层设计,进程通常运行在用户态,权限受限,不能直接操作硬件资源,而操作系统内核运行在内核态,拥有最高权限,负责管理和协调所有硬件设备,因此,当键盘产生输入信号时,首先接收到并处理该信号的是操作系统内核

在早期的计算机系统中,轮询是一种检测外设状态的方法,操作系统会按照一定的时间间隔,主动去检查键盘设备文件的状态,看是否有新的数据产生,如果有数据,就将其从键盘外设读取到内核的文件页缓冲区,以便后续处理 现代计算机系统通常会连接多个不同类型的外设,如鼠标、键盘、打印机、网卡等,如果对每个外设都采用轮询方式进行检查,CPU 会花费大量的时间在不断查询外设状态上,而无法高效地执行其他重要任务,这会严重降低系统的整体性能,所以,现代操作系统一般不采用这种方式来处理外设数据

在计算机的体系结构中,CPU 和外设之间的数据传输往往需要借助 I/O 接口电路和相应的控制器,CPU 一般不会直接与外设进行数据通信,但是,当外设产生新的数据时,外设可以通过中断控制器向 CPU 发送一个硬件中断信号,通知 CPU 有新的数据需要处理

为了区分不同外设发出的中断信号,每个中断都被分配了一个唯一的中断号,当 CPU 接收到中断信号后,会根据中断号来确定是哪个外设产生了中断,操作系统维护着一个中断向量表,该表存储了每个中断号对应的中断处理程序的入口地址,CPU 以中断号为下标,从中断向量表中获取相应的中断处理程序入口地址,然后跳转到该地址执行中断处理程序,从而完成对外设数据的处理

当用户按下键盘上的按键时,操作系统会对输入的内容进行解析,输入内容可以分为普通数据(如用户输入的字母、数字等)和控制信息(如组合键、功能键等),以ctrl+c组合键为例,操作系统会识别ctrl+c组合键,并将其转换为SIGINT信号(信号编号为 2),然后将该信号发送给当前正在运行的前台进程,进程接收到该信号后,通常会执行相应的操作(如终止进程)

我们所学习的信号,就是用软件的方式,对进程模拟的硬件中断

3、产生方式

首先我们要知道的是:不管信号的产生方式有多少中,信号是由操作系统发送给进程的,因为操作系统是进程的管理者

我们信号学习的第一个产生的方式就是键盘组合键,ctrl+c中断、ctrl+z暂停等等

我们学习过程中知道的第二个产生的方式就是kill命令,通过配合不同的选项可以达到不同的效果

第三个产生的方式就是系统调用,类似于int kill(pid_t pid, int sig);在进程中杀死另一个进程

第四个产生的方式就是程序异常,比如说除数为0的情况,或者野指针的情况

第五个产生的方式就是通过软件模拟形成闹钟

(一)键盘组合键

我们前面已经解释过键盘组合键产生信号的原因了,这里我们来介绍一下后台程序

Linux Omniscient
Linux Omniscient

>全知全能技能Linux版。

下载
后台程序

我们在上面解释过了程序组合键ctrl+c可以中断前台进程,但后台进程是奈何不了的,我们正常执行的进程是前台进程,在我们正常执行程序的命令后面加一个&,可以将程序转到后台执行

【Linux】进程信号的产生

首先我们看到第一行的打印[1] 13128,其中方括号内的数字叫做作业编号,它是由shell分配给每个后台作业的一个唯一标识符,它是线性递增的,如果我有三个进程在后台运行,作业编号分别为123,我杀死作业编号为2的进程后,再运行一个新的后台进程,它的作业编号是2,后面那个数字就是进程PID

我们知道我们在打开终端后,默认在前台运行的就是bash进程,在正常执行进程的时候它就跑到后台了,我们做了一个小实验,在后台程序test执行过程中,我输入了ls命令,不难看出他也打印出来了我们对应的内容,此时前台就是bash进程,此时再按ctrl+c就不会被捕捉了,因为键盘的输入只会被前台进程读取

(二)命令

命令就不多说了,就是kill命令后面加上信号编码,表示是什么信号

(三)系统调用

kill的作用就是指定信号发送给指定进程

代码语言:javascript代码运行次数:0运行复制
#include <sys/types.h>#include <signal.h>int kill(pid_t pid, int sig);

返回值:调用成功返回0,失败返回-1 pid:指定要接受信号的进程PID sig:要发送的信号编号

raise:的作用就是进程自己给自己发信号

代码语言:javascript代码运行次数:0运行复制
#include <signal.h>int raise(int sig);

返回值:成功返回0,失败返回非0 sig:要发送的信号编号

abort的作用是异常终止当前的进程

代码语言:javascript代码运行次数:0运行复制
#include <stdlib.h>void abort(void);
(四)程序异常(1)除0异常
【Linux】进程信号的产生
【Linux】进程信号的产生

我们可以看到除0前的打印执行了,除0后的打印没有执行,这是为啥呢?

程序中的计算任务由 CPU 执行,CPU 设有特定寄存器用于存储操作数,同时还有一个状态寄存器,它包含多个比特位级别的标记位,其中一个标记位专门用于指示当前运算是否发生异常,当 CPU 执行除 0 操作时,会触发异常,此时 CPU 会修改状态寄存器中相应的异常标记位,寄存器中的内容属于当前进程的上下文数据,在进行进程切换时,这些数据会被替换为即将执行的其他进程的上下文数据;而当该进程再次获得 CPU 执行权时,其上下文数据又会被恢复,通常情况下,非严重异常仅会对当前进程产生影响

CPU 作为硬件资源,操作系统作为硬件的管理者,需时刻关注硬件状态,当 CPU 中的异常标志位被设置时,会触发中断机制,此时,CPU 会暂停当前程序的执行,保存现场信息(如程序计数器、寄存器值等),然后根据中断向量表转去执行对应的中断处理程序,操作系统在中断处理程序中感知到异常后,会依据异常的具体类型,向引发异常的进程发送相应的信号,比如 SIGFPE,以此通知进程处理异常情况

(2)野指针异常
【Linux】进程信号的产生
【Linux】进程信号的产生

空指针解引用和越界访问这一类的问题都是虚拟内存通过页表映射到物理内存的时候出错,导致硬件报错,进而被操作系统识别

(3)总结

程序对于异常信号,默认动作是让程序立即终止,但是我们可以在程序中对异常信号进行捕捉,如果捕捉方法里没有做退出的特殊处理,那这导致的后果就是程序不会立即终止,而是一直被调用运行,硬件错误就一直存在,操作系统就会一直给进程发送异常信号,因为它的状态寄存器中相应的异常标记位在这个进程离开CPU之前是不会改变的

(五)软件模拟—alarm闹钟

alarm用于设置一个定时器,在指定的秒数后向进程发送SIGALRM信号,如果在seconds秒后没有其他操作来处理SIGALRM信号,进程通常会终止并产生一个默认的行为

代码语言:javascript代码运行次数:0运行复制
#include <unistd.h>unsigned int alarm(unsigned int seconds);

返回值:如果之前没有设置过定时器,返回 0,如果之前已经设置过定时器,返回距离下一次定时器到期剩余的秒数 seconds:秒数

【Linux】进程信号的产生
【Linux】进程信号的产生

5秒后捕捉到闹钟信号,执行信号处理函数

如果我们想定时执行某个任务task,实现如下的结构

【Linux】进程信号的产生
【Linux】进程信号的产生

在闹钟响后再定个五秒的闹钟,像不像早上赖床的你,这里的任务就是睡觉,main函数中的alarm就是你昨晚上定的闹钟,信号处理函数中的alarm就是早上闹钟响后你按下的10分钟后再响

函数体搞明白了,我们再解释一下它的返回值

【Linux】进程信号的产生
【Linux】进程信号的产生

我们在进程main函数发送alarm之前发送14号信号,可以看到这里的剩余时间就是设定的时间减去main函数执行的时间,此时跳到信号处理函数执行,重新设置alarm,5秒后再响铃剩余时间就是0了

事实上,alarm有管理它的结构体,你可以简单理解为,在调用的时候返回值是存在于结构体某个成员变量中的(返回值事实上是经过转换后得出的结果),然后在下次调用alarm的时候返回的是上次alarm的剩余时间,之后更新结构体中的信息,以设置新的定时器

今日分享就到这里了~

热门AI工具

更多
DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

Flowith
Flowith Hot

Flowith是一款基于画布和智能体工作流的 AI 协作工作空间。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

354

2023.09.25

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

17880

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

1263

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

9590

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

3822

2025.08.07

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

5414

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

5591

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

7459

2023.08.02

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

0

2026.11.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn