news 2026/4/18 3:34:43

Linux信号处理函数中断流程分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux信号处理函数中断流程分析

Linux中信号处理函数的执行可能会中断其他正在执行的流程,但具体行为取决于中断的类型和执行上下文。以下是详细分析:

1.信号处理中断的两种情况

A.用户态执行被中断

当进程在用户态执行时,信号处理函数会中断正常的程序流程:

// 示例:普通用户代码执行被信号中断intmain(){// 设置SIGINT的信号处理函数signal(SIGINT,sig_handler);while(1){// 正常执行的代码printf("Working...\n");sleep(1);// 如果此时收到SIGINT,会立即跳转到sig_handler执行}}

特点:

  • 信号处理函数执行完毕后,返回原程序继续执行
  • 类似于函数调用,但有特殊的上下文切换

B.系统调用被中断

当进程执行系统调用时,信号处理可能中断系统调用:

// 系统调用可能被信号中断intmain(){signal(SIGALRM,handler);// 如果read()阻塞期间收到信号charbuf[100];intn=read(STDIN_FILENO,buf,sizeof(buf));// 可能被中断if(n==-1&&errno==EINTR){// 系统调用被信号中断printf("System call interrupted by signal\n");}}

2.不同场景的详细分析

场景1:单线程进程

// 信号处理函数执行时,主程序完全暂停voidhandler(intsig){// 执行期间,主程序代码不会执行printf("Signal received\n");// 除非处理函数中调用了长耗时操作,否则很快返回}
  • 主程序流程被中断,直到处理函数返回
  • 不可重入函数可能导致问题(如printf、malloc)

场景2:多线程进程

// 多线程中,信号处理更加复杂pthread_ttid1,tid2;void*thread_func(void*arg){// 线程有自己的信号掩码sigset_tset;sigemptyset(&set);sigaddset(&set,SIGINT);pthread_sigmask(SIG_BLOCK,&set,NULL);// 这个线程不会响应SIGINT}
  • 默认情况下,信号发送到进程,但由任意一个线程处理
  • 特定信号可以定向到特定线程
  • ✅ 信号处理期间,其他线程可能继续执行

场景3:内核态执行

// 当进程在内核态执行时intmain(){// 执行系统调用进入内核态write(fd,buffer,size);// 如果在内核态期间收到信号:// 1. 某些系统调用可被中断(慢速设备I/O)// 2. 某些系统调用不会被中断(磁盘I/O通常完成或重启)}
  • ⚠️某些内核操作不可中断(如磁盘I/O完成阶段)
  • ⚠️ 信号处理延迟到返回用户态时
  • ⚠️ 中断系统调用可能返回EINTR错误

3.关键技术和行为控制

控制信号中断行为

structsigactionsa;// 设置SA_RESTART标志,让被中断的系统调用自动重启sa.sa_flags=SA_RESTART;sigaction(SIGINT,&sa,NULL);// 或者使用siginterrupt控制特定信号是否中断系统调用siginterrupt(SIGINT,1);// 1=中断,0=不中断// 设置信号处理期间屏蔽其他信号sigemptyset(&sa.sa_mask);sigaddset(&sa.sa_mask,SIGQUIT);// 处理SIGINT时屏蔽SIGQUIT

异步信号安全函数

在信号处理函数中,只能使用异步信号安全函数

voidhandler(intsig){// 安全的:write, read, _exit, signal等write(STDOUT_FILENO,"Signal\n",7);// 不安全的:printf, malloc, free等// printf("Signal %d\n", sig); // 危险!// 设置标志让主程序处理volatilesig_atomic_tflag=1;}

4.特殊情况

实时信号(RT信号)

// 实时信号排队,不会被丢失sigaction(SIGRTMIN,&sa,NULL);// 多个SIGRTMIN信号会排队处理

信号处理函数中的非局部跳转

#include<setjmp.h>jmp_buf env;voidhandler(intsig){longjmp(env,1);// 直接跳转,中断处理流程}intmain(){signal(SIGINT,handler);if(setjmp(env)==0){// 正常执行}else{// 从信号处理跳转回来}}

5.总结表格

执行上下文是否被中断备注
用户态代码✅ 是立即跳转到处理函数
可中断系统调用✅ 是返回EINTR错误
不可中断系统调用⚠️ 延迟完成后再处理信号
多线程(信号屏蔽)❌ 否被屏蔽信号的线程不受影响
信号处理函数自身⚠️ 可能除非设置SA_NODEFER
内核关键路径❌ 否完成关键操作后再处理

6.最佳实践建议

  1. 保持处理函数简短- 只设置标志,不做复杂操作
  2. 使用sigaction而非signal- 更可控的行为
  3. 考虑使用signalfd- 将信号转为文件描述符事件
  4. 多线程中使用pthread_sigmask- 精确控制信号传递
  5. 检查EINTR错误- 正确处理被中断的系统调用
// 推荐:使用signalfd将信号整合到事件循环intsfd=signalfd(-1,&mask,0);// 现在可以在epoll/poll/select中处理信号

信号处理是Linux编程中的高级话题,需要仔细设计以避免竞态条件和未定义行为。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/14 11:45:22

星巴克中国与亚朵集团达成合作推出联合会员计划 | 美通社头条

、美通社消息&#xff1a;1月6日&#xff0c;星巴克中国宣布与亚朵集团达成合作&#xff0c;携手推出联合会员计划&#xff0c;标志着星享俱乐部的会员权益再度加码。加入联合会员的金星、钻星会员&#xff0c;可体验一年至高360天亚朵金会员核心权益&#xff0c;享受"升级…

作者头像 李华
网站建设 2026/4/13 20:24:37

Mac隐藏效率神器

每当深夜敲代码时&#xff0c;我最怕的不是bug难解&#xff0c;而是思路被突如其来的操作打断。想象这样一个场景&#xff1a;你在IDE里调试得正投入&#xff0c;突然需要执行一个本地测试脚本。本能反应是切到终端、定位目录、输入命令——这一套操作下来&#xff0c;刚才清晰…

作者头像 李华
网站建设 2026/4/11 2:36:20

气体检测仪的应用:CCUS二氧化碳捕集驱油过程泄露监测方案

随着双碳目标的推进&#xff0c;CCUS技术&#xff0c;尤其是二氧化碳驱油&#xff0c;已成为石油开采行业降本增效与绿色转型的关键路径。然而&#xff0c;在二氧化碳的注入、输送、驱油及封存的全流程中&#xff0c;管道、阀门、井口及地表可能存在泄露风险。这不仅造成宝贵资…

作者头像 李华
网站建设 2026/4/16 19:04:27

大数据领域数据标注的创新技术与趋势

大数据时代的数据标注革命&#xff1a;创新技术、实践痛点与未来趋势 摘要/引言 你知道训练一个能精准识别肺癌的AI模型需要多少标注数据吗&#xff1f;答案是至少5万张带病灶定位的CT影像——而这只是医疗AI领域的“基础需求”。当我们迈入大数据时代&#xff0c;全球每天产生…

作者头像 李华
网站建设 2026/4/17 21:11:50

sv中的三种case

在SystemVerilog中&#xff0c;case、casex和 casez是三种不同的条件选择语句&#xff0c;它们在匹配规则上有重要区别&#xff1a;1. 基本区别语句通配符匹配规则可综合程度case无精确匹配完全可综合casez?和 z将 z和 ?视为"不关心"可综合&#xff0c;但需谨慎cas…

作者头像 李华
网站建设 2026/4/12 10:16:42

《打破边界:云服务器的多元形态进化史》

《打破边界&#xff1a;云服务器的多元形态进化史》当人们提及云服务器&#xff0c;往往先想到阿里云ECS、腾讯云CVM等传统虚拟机&#xff0c;但如今“云服务器”的定义已突破单一形态&#xff0c;演化出覆盖公有云、私有云、边缘计算、无服务器的多元生态。从虚拟化到容器化&a…

作者头像 李华