信号生命周期

本文档描述了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 系统调用,通知内核。内核读取用户栈上的保存的上下文信息,恢复进程被中断前的寄存器状态,进程继续执行原有代码。