当前位置: 首页 > news >正文

浅析Linux进程信号处理机制:基本原理及应用

文章目录

    • 概述
    • 信号类型
      • 可靠信号与不可靠信号
      • Fatal信号与Non Fatal信号
      • 不可捕获/忽略信号
    • 信号工作机制
      • 信号处理方式
      • 信号嵌套处理
    • 信号使用
      • 信号发送
        • kill命令
      • 注册信号处理函数
    • 信号安全与函数可重入性
      • 可重入函数
      • 线程安全与可重入性
    • 相关参考

概述

Linux信号机制是进程间通信的一种方式,用于在不同进程之间传递信息,它通过向目标进程发送一个特定的信号,来触发目标进程执行相应的处理操作。信号本质上是在软件层次上对中断机制的一种模拟,可以认为是用户态下的中断机制,它为用户进程提供了一种处理异步事件的方法;用户进程可以注册自定义的信号处理函数,在进程响应外部信号时,会自动调用回调进行处理。

信号类型

Linux定义了64种信号类型,每个信号都有唯一的编号进行标识。在系统中,通过kill -l命令可以查看所有的信号类型。

可靠信号与不可靠信号

Linux信号可以分为不可靠信号和可靠信号。

  • 不可靠信号:又称非实时信号,是指在信号传递过程中可能丢失或产生不可预测行为的信号,这意味着当一个进程接收到该信号时,无法确保该信号一定会被进程处理。1-31号信号为不可靠信号
  • 可靠信号:又称实时信号,是保证传递和处理的信号。当一个进程接收到可靠信号时,系统会确保该信号不会丢失,并且会等待进程处理完该信号后再继续执行其他操作,Linux使用队列来保存待处理的信号,保证它们按照接收的顺序被进程处理。34-64号信号为可靠信号

在日常开发及维护时,见到的基本是不可靠信号:
在这里插入图片描述

Fatal信号与Non Fatal信号

对于每一个信号,系统都有默认的处理行为,根据信号的默认处理行为,可以将信号分为 Fatal(致命)信号和 Non-Fatal(非致命)信号。

  • Fatal信号:Fatal 信号是指那些默认处理行为会导致进程终止的信号。当进程收到这类信号且没有注册自定义处理函数时,进程会被终止。
  • Non Fatal信号:Non-Fatal 信号是指那些默认处理行为不会导致进程终止的信号。这些信号通常用于控制进程状态或通知特定事件。

不可捕获/忽略信号

在Linux系统中,用户通常可以捕获信号,并自定义处理信号处理行为;但有两个信号比较特殊,它们既不能忽略,也不能捕获,只能执行默认处理:

  • SIGKILL (9):强制终止进程
  • SIGSTOP (19):暂停进程

信号工作机制

与中断的实时响应(CPU执行完一条指令后,就会响应中断请求)不同,进程对信号的处理有一定的滞后性。原因在于,当应用进程接收到其它进程发送的信号时,不会立即做出响应,只有等当前进程陷入到内核空间时,才会进行信号检测。Linux系统中,应用程序处理信号的流程示意如下:
在这里插入图片描述

可以看到,系统对信号的检测与响应总是发生在内核态,只有当前进程由于系统调用、中断或异常而进入系统空间以后,从系统空间返回到用户空间的前夕,内核才会进行信号的处理。

检测到信号后,内核在用户栈创建新层,将返回地址指向信号处理函数,确保函数在用户态执行,避免权限泄露;信号处理程序执行完成后,会执行sigreturn系统调用再次切换到内核态,再由恢复原系统调用或代码执行点。

信号处理方式

在进程接收到一个信号时,可以告诉内核按照下列三种方式之一进行处理:

  • 忽略信号:对信号不做任何处理(但 SIGKILL 和 SIGSTOP 不能被忽略);
  • 捕获信号:注册自定义的信号处理函数;
  • 默认处理:执行系统定义的默认动作。Linux信号的默认处理行为可以分为以下几类:
    • Terminate:终止进程;
    • Coredump:终止进程并生成核心转储文件;
    • Ignore:忽略信号;
    • Stop:暂停进程;
    • Continue:继续运行进程。

信号嵌套处理

默认情况下,信号处理函数运行期间,如果再次接收到相同信号,信号会被自动阻塞,直到当前处理函数执行完毕。

信号使用

在日常开发或维护过程中,所涉及到信号的使用方式,主要是如何发送信号以及自定义程序的信号的处理行为。

信号发送

Linux系统使用kill系统调用向指定进程发送信号,原型定义如下:

 #include <sgnal.h> 
int kill(int pid, int sign);

kill函数的pid参数根据取值有多重含义:

  • pid>0:将此信号发送给进程ID为pid的进程;
  • pid=0:将此信号发送给进程组ID和该进程相同的进程;
  • pid<0:将此信号发送给进程组内进程ID为pid的进程;
  • pid=-1:将此信号发送给系统所有的进程。
kill命令

在Linux系统中,kill命令用于向进程发送信号,以终止或控制进程。默认情况下,kill命令发送的是SIGTERM(终止信号),这通常会让进程自行清理资源并优雅地终止。如果进程没有响应SIGTERM,可以使用SIGKILL(杀死信号)强制终止进程。

kill [-signum] [PID]

注册信号处理函数

Linux系统下可以通过signalsigaction函数可以注册信号处理函数。signal原型如下:

#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
sigaction是 signal的增强版,提供了更精细的控制,包括:
* 自定义信号处理函数
* 设置信号屏蔽字(阻塞其他信号)
* 指定信号处理标志(如是否自动重置处理函数)

sigaction函数原型定义如下:

#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

信号安全与函数可重入性

信号安全是指线程在信号处理函数当中,不管以任何方式调用你的函数如果不死锁不修改数据,那就是信号安全的。在信号处理函数中应避免调用不可重入的函数(如 printf、malloc),否则可能导致程序崩溃。

可重入函数

一个函数或代码段若能在被中断后安全地再次调用(如信号处理函数中调用),则称为可重入的。不可重入的代码会导致数据损坏或死锁。
可重入代码的条件:

  1. 不使用全局或静态变量:依赖局部变量或通过参数传递状态。
  2. 不调用不可重入函数:如malloc()、printf()、非线程安全的库函数。
  3. 避免锁的嵌套:信号处理函数中不应获取锁(可能引发死锁)。
    在这里插入图片描述

线程安全与可重入性

可重入函数是线程安全函数的一个真子集。可重入函数一定是线程安全的。尽管线程安全和可重入有时会被不正确地用作同义词,但它们之间有清晰的技术差别。线程安全函数可能使用同步机制(如锁)来保护共享数据,而可重入函数则完全不使用共享数据。

相关参考

  • 《Unix环境高级编程》
  • Linux signal 图文详解(一)信号简介、信号注册
  • 干货】linux内核信号的处理过程

文章转载自:

http://h1d7JhfC.stcds.cn
http://qRBlKKhD.stcds.cn
http://Uk93Dtjm.stcds.cn
http://OCAKvbKW.stcds.cn
http://DIzL0Gz6.stcds.cn
http://zyi6KYx2.stcds.cn
http://dM6EmtcI.stcds.cn
http://jXjkJHMo.stcds.cn
http://L5KZkv5F.stcds.cn
http://2yFZkmUV.stcds.cn
http://44LHWVKx.stcds.cn
http://H1VrGu7j.stcds.cn
http://xtMCQsgg.stcds.cn
http://j0iF454K.stcds.cn
http://WJ7o2qnZ.stcds.cn
http://1ftKrBM1.stcds.cn
http://eutOnSB3.stcds.cn
http://afqaImeU.stcds.cn
http://ORUCH7Xj.stcds.cn
http://p9NpSKm2.stcds.cn
http://4X1kuV8c.stcds.cn
http://GGLkvhED.stcds.cn
http://gto3PZ8U.stcds.cn
http://VabVAscX.stcds.cn
http://9nx5RJkr.stcds.cn
http://ObVQYvSy.stcds.cn
http://APMkfSCM.stcds.cn
http://7jEH4f3O.stcds.cn
http://Fz9uqPz5.stcds.cn
http://4Ke3loze.stcds.cn
http://www.dtcms.com/a/382131.html

相关文章:

  • php学习(第五天)
  • C盘清理技巧分享的技术文章大纲
  • PINN物理信息神经网络驱动的三维声波波动方程求解MATLAB代码
  • 深度学习优化器进化史:从SGD到AdamW的原理与选择
  • 计算机视觉(opencv)实战十九——角点检测图像特征(Harris 角点、Shi-Tomasi 角点)
  • 【限流器设计】固定窗口计数法
  • Estimator and Confidence interval
  • 构建AI智能体:三十二、LangChain智能体:打造会使用工具(Tools)、有记忆(Memory)的AI助手
  • AI内容标识新规实施后,大厂AI用户协议有何变化?(六)科大讯飞
  • 机械应答到自然交流,声网AI陪练改变我的口语
  • 贪心算法应用:信用评分分箱问题详解
  • 【Spring AI】Filter 简单使用
  • html各种常用标签
  • Linux 进程信号之信号的捕捉
  • 实验-高级acl(简单)
  • C++之特殊类设计
  • stm32教程:USART串口通信
  • 地级市绿色创新、碳排放与环境规制数据
  • ES——(二)基本语法
  • 中级统计师-统计法规-第十一章 统计法律责任
  • 拥抱直觉与创造力:走进VibeCoding的新世界
  • Python进程和线程——多进程
  • 论文阅读 2025-9-13 论文阅读随心记
  • leecode56 合并区间
  • 用R获取 芯片探针与基因的对应关关系 bioconductor的包的 三者对应关系
  • xxl-job的使用
  • 2025 年 9 月 12 日科技前沿动态全览
  • 高德地图自定义 Marker:点击 悬停 显示信息框InfoWindow实战(Vue + AMap 2.0)
  • 猿辅导Java后台开发面试题及参考答案
  • 启动项目提示:org.springframework.context.annotation不存在问题