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

对信号的理解

  1. 调用 alarm(secs)进程调用 alarm(secs) 时,内核会立即检查并取消之前设置的任何待处理闹钟(如果有的话),并返回上次闹钟剩余的秒数。

    • 如果 secs 是 0,则不设置新闹钟,只取消旧的。
    • 如果 secs 是正数,内核会在 secs 秒后向该进程发送 SIGALRM 信号。
  2. 内核调度闹钟内核记录下闹钟的触发时间,并在计时到期时,修改该进程的 pending 信号位图,标记 SIGALRM 待处理。

  3. 进程响应 SIGALRM当进程下一次进入内核态(比如系统调用结束、时间片切换)时,内核会检查到 SIGALRM 信号,调用对应的处理函数(默认是终止进程)。

简单来说,alarm 函数相当于让内核在指定时间后 “唤醒” 进程并给它一个 SIGALRM 信号。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>void sig_handler(int signum) {printf("收到 SIGALRM 信号,程序结束\n");exit(0);
}int main() {// 注册信号处理函数signal(SIGALRM, sig_handler);// 设置 5 秒后发送 SIGALRM 信号alarm(5);printf("程序开始运行,5 秒后会自动结束\n");// 让程序在这里循环,直到信号触发while (1) {printf("等待...\n");sleep(1);}return 0;
}

运行流程是:

  1. 程序启动后,调用 alarm(5),内核开始计时 5 秒。
  2. 程序进入 while(1) 循环,每隔 1 秒打印一次 “等待...”。
  3. 5 秒后,内核向当前进程发送 SIGALRM 信号。
  4. 进程收到信号,执行 sig_handler 函数,打印结束信息并退出。

调用 alarm(5) 时,内核并不会直接把 SIGALRM 放到进程的 pending 信号里,而是做了一个 “预约”:

  • 内核记录下当前时间,加上 5 秒,得到闹钟的触发时间。
  • 然后内核把这个闹钟 “挂” 在当前进程上,等待时间到期。
  • 这时候进程的 pending 信号里是没有 SIGALRM 的,因为信号还没到触发时间。

等到5 秒时间到了,内核才会:

  1. 把 SIGALRM 信号放到进程的 pending 信号队列中。
  2. 等进程下次陷入内核态(比如系统调用结束、时间片用完)时,内核检查到 pending 里的 SIGALRM
  3. 暂停当前程序执行,去调用 sig_handler

简单来说:alarm(5) → 预约(不立即发信号)5 秒后 → 内核放入 pending → 触发处理函数

内核在收到 alarm(secs) 调用时,并不会立刻把 SIGALRM 放到 pending 里,而是先在内部设置一个定时器

流程是这样的:

  1. 调用 alarm(5) → 内核记下 “5 秒后要发 SIGALRM”。
  2. 这时候 pending 里没有 SIGALRM,进程继续正常运行。
  3. 5 秒后 → 内核才会把 SIGALRM 信号放到 pending 队列。
  4. 进程下一次进入内核态(比如系统调用结束、时间片切换)时,内核检测到 pending 中的 SIGALRM,触发信号处理。

在 Linux 内核和进程信号处理的语境里,pending 通常翻译成 **“待处理”“挂起”**。

它指的是已经发送给进程、但进程还没来得及处理的信号,保存在进程的 pending 信号位图里。只有当进程进入内核态时,内核才会检查这个位图,并处理其中的信号。

  1. 触发信号处理一定会执行 sig_handler:只要内核检测到 pending 中的 SIGALRM,且你已经通过 signal 或 sigaction 为该信号注册了 sig_handler 作为处理函数,就会暂停当前程序执行,转而调用 sig_handler
  2. sig_handler 是在用户态执行的:信号处理函数由用户自己编写,内核不会在核心态执行用户代码 —— 内核会先完成 “暂停当前进程、保存上下文” 等核心态操作,然后切换到用户态,再去执行 sig_handlersig_handler 执行完后,会切回内核态恢复原进程上下文,让原程序继续运行。

sig_hsnder的执行会单独再起一个进程吗?

不会,sig_handler(信号处理函数)不会单独启动新进程,它是在当前进程的上下文里执行的。

具体流程可以拆解为 3 步,更清晰理解为什么不用新进程:

  1. 当内核检测到 pending 中的 SIGALRM 时,会先暂停当前进程正在执行的代码,并保存当前进程的上下文(比如 CPU 寄存器值、程序计数器等,记录 “暂停时执行到哪了”)。
  2. 然后内核会切换到用户态,在当前进程的地址空间里,直接调用 sig_handler 执行信号处理逻辑(相当于 “插队” 执行,用的还是原进程的资源)。
  3. sig_handler 执行完后,内核会恢复之前保存的进程上下文,让原进程从暂停的位置继续往下执行。

简单说:sig_handler 是当前进程的 “临时任务”,不是新进程 —— 就像你写代码时,中途停下来处理一个消息,处理完再接着写,不会重新开一个新的代码文件去处理消息。

如果信号处理要启动新进程,需要你在 sig_handler 里主动调用 fork() 函数,否则默认就是在当前进程里执行。

其他信号触发时,是不是没有时间等待,系统直接往对应接收信号的进程的上下文中中的pending中添加信号事件?

是的,当信号触发时,系统会直接往对应接收信号的进程的上下文中的pending(未决信号集)中添加信号事件。

信号产生后,内核并不会立即将其递送给进程处理,而是先将信号标记为 “待处理(pending)”,存放在进程的进程控制块(PCB)即task_struct结构体中。pending是一个位图,每个比特位对应一个信号,当信号触发时,内核会在pending位图中设置相应的比特位,表示该信号已产生但未被处理。如果信号没有被阻塞,内核会在进程从用户态切换到内核态后,返回用户态前检查并递送该信号;如果信号被阻塞,则会一直留在pending集合中,直到阻塞解除。

http://www.dtcms.com/a/537252.html

相关文章:

  • 【系统分析师】高分论文:论软件的安全性设计(某校通系统)
  • 硬盘专业名词:总线、协议、接口详细解析
  • Agent Skills应用解析:构建可扩展、高效率AI探员
  • 【车载测试常见问题】CAN一致性测试包含哪些内容?
  • 成都网站开发制作上海进博会
  • 云手机和虚拟机的区别都有哪些?
  • php wap网站实现滑动式数据分页大公司网站开发
  • WebSocket 详解
  • SPR 实验笔记:从原理到实操,解锁天然产物筛选、靶点验证与膜蛋白互作的“金标准”技术
  • 发布会回顾|袋鼠云发布多模态数据中台,重构AI时代的数据底座
  • AOI在PCB制造领域的核心应用
  • 网站建设系统规划seo信息优化
  • 建筑公司网站设计思路静态网站怎么样
  • python在Linux服务器中安装
  • 排序算法解析
  • 餐饮 网站建设互联斗士网站建站
  • 民营医院网站建设视频网站点击链接怎么做
  • Java 大视界 -- Java 大数据机器学习模型在游戏用户行为分析与游戏平衡优化中的应用
  • 微信小程序-智慧社区项目开发完整技术文档(上)
  • 2025年10月主流工程项目管理软件推荐
  • 设计模版网站一级a做爰片365网站
  • 计算机网络自顶向下方法7——应用层 HTTP概述及其连接方式
  • 网站建设贵不贵wordpress站文章显示时分秒
  • 【编译原理笔记】3.4 Tokens Recognization
  • day19_添加修改删除
  • 【Linux】ps -ef 和 ps -aux的区别
  • OpenFeign与Sentinel集成的原理
  • window系统下利用anaconda安装labelImag
  • Windows开机启动命令
  • LocalDream 2.1.2 |在手机设备上运行SD模型,支持文本到图像生成和图像重绘,无任何限制