信号生命周期
本文档描述了IPC子系统中的信号机制及其工作流程
概述
信号是系统中用于实现异步事件通知的 IPC(进程间通信)机制。信号的处理过程被划分为三个核心阶段:发送、递送和处理,由内核的不同子系统和架构代码负责。
I. 信号的产生与发送(Sending)
这一阶段的目标是将信号标记给目标进程,使其进入**挂起(Pending)**状态。
1. 事件触发与系统调用
- 负责者: 用户程序、硬件、C 库 (
glibc)。 - 过程:
- 软件触发: 用户调用
kill()、raise()等函数,这些函数通过 C 库包装,最终执行syscall指令进入内核态。 - 硬件触发: 如除零 (
SIGFPE) 或非法内存访问 (SIGSEGV) 等异常,由 CPU 捕获后交由内核的异常处理程序处理。 - 内核触发: 如定时器到期 (
SIGALRM),由内核的计时器子系统发送。
- 软件触发: 用户调用
2. 内核标记
- 负责者: 内核的进程管理子系统和信号子系统。
- 过程:
- 内核检查发送方权限。
- 内核在目标进程的 PCB (
task_struct) 中,修改其pending信号位图,将信号标记为已到达。 - 如果目标进程正在阻塞等待,内核可能会将其唤醒。
II. 信号的检查与递送(Delivering)
这一阶段负责在最安全的时机将信号插入进程的执行流。
3. 检查点(Checkpoint)
- 负责者: 内核的系统调用和中断返回路径。
- 时机: 进程执行完成一个系统调用、中断或异常处理,即将从内核态返回到用户态的瞬间。
- 过程: 内核检查当前线程是否有待处理的挂起信号。
4. 递送决策
- 负责者: 内核信号子系统。
- 过程:
- 屏蔽检查: 检查信号是否被当前线程的信号屏蔽集 (
blocked) 屏蔽。如果被屏蔽,信号保持挂起,不进行处理。 - 处理方式判断: 检查进程的信号处理表 (
sighand),确定信号处理方式:默认、忽略,或用户自定义函数。
- 屏蔽检查: 检查信号是否被当前线程的信号屏蔽集 (
III. 信号的处理与返回(Handling)
最终的处理操作,可能在内核态完成,也可能在用户态完成。
5. 最终处理操作
选项 A:内核处理(默认或忽略)
- 负责者: 内核进程/信号子系统。
- 过程: 如果信号是忽略 (
SIG_IGN),内核直接清除pending标志并恢复执行。如果信号是默认行为(如SIGKILL),内核在内核态直接终止或修改进程状态。
选项 B:用户处理(捕获)
- 负责者: 内核的架构相关代码。
- 过程:
- 内核将原有的用户态寄存器上下文和信号信息压入用户栈,构建信号栈帧。
- 内核修改进程的程序计数器(PC/RIP),指向用户注册的信号处理函数地址。
- 进程返回用户态后,立即开始执行 Handler 代码。
6. 恢复执行
- 负责者: C 库的
sigreturn()函数和内核。 - 过程: 用户 Handler 执行完毕后,调用
sigreturn系统调用,通知内核。内核读取用户栈上的保存的上下文信息,恢复进程被中断前的寄存器状态,进程继续执行原有代码。