信号是传递给进程或特定线程的异步通知。信号用于报告事件和请求操作,但与面向数据的进程间通信机制相比,只能携带有限信息。
进程 · 第 6 课
信号
学习 Linux 如何生成、阻塞、传递和处理信号,以控制进程并通知事件。
信号的来源
信号可以来自多个地方:
- 终端可以为
Ctrl-C生成SIGINT,为Ctrl-Z生成SIGTSTP,并发送给前台进程组。 - 线程进行无效内存引用时,内核可以生成
SIGSEGV等同步信号。 - 进程可以向另一个进程或进程组发送获准信号。
- 定时器、子进程状态变化和终端挂断可以生成其他信号。
发送者必须拥有适当权限,通常由凭据或 capabilities 决定。因此,信号是由内核中介的控制接口,而不是任意用户之间不受限制的消息。
终端通常会为 Ctrl-C 生成哪个信号?
处置方式和默认操作
大多数信号都有进程范围的处置方式,从三种响应中选择一种:
- 执行该信号定义的默认操作
- 忽略信号
- 调用用户安装的处理程序
默认操作各不相同:信号可以终止、终止并创建 core dump、停止、继续,也可以被忽略。捕获 SIGTERM 可以让程序开始有序关闭,但处理程序必须遵循严格的异步信号安全规则,程序也仍可能延迟或拒绝退出。
信号名称比数字更易移植和阅读。虽然常见 Linux 架构使用 15 表示 SIGTERM,但除相关标准保证的数字外,不要假设所有信号编号在各处都相同。使用 kill -l 检查本地映射。
为什么进程可以优雅地响应 SIGTERM?
被阻塞和待处理的信号
线程拥有信号掩码,可以暂时阻塞选定信号的传递。已经生成但被阻塞的信号会保持待处理状态,直到可以传递,但仍受标准信号和实时信号规则约束。同一类型的标准信号可能合并,而不是按每次出现逐个排队。
在多线程进程中,面向进程的信号可以传递给未阻塞它的适当线程;面向线程的信号则以指定线程为目标。因此,正确的信号设计不能只检查“进程是否阻塞了它”。
目标阻塞一个可阻塞信号时,生成该信号通常会发生什么?
无法处理的信号
SIGKILL 会终止进程,SIGSTOP 会停止进程。这两个信号都不能被捕获、忽略或阻塞。这保证内核保留最终控制权,但也意味着 SIGKILL 不会给应用层清理留下机会。
即使是 SIGKILL,从观察者角度看也可能不会让任务立即消失。任务可能正在等待不可中断的内核操作,终止后其父进程仍需回收状态。
哪一对信号不能被捕获、忽略或阻塞?
课程已完成
你已完成 信号
现在,你可以说明 Linux 信号处理的主要阶段和限制。
识别由终端、内核和进程生成的信号。
区分默认操作、忽略信号和处理程序。
把阻塞与待处理传递及线程掩码联系起来。
记住
SIGKILL和SIGSTOP无法被处理或阻塞。