# 8.5 信号

到目前为止对异常控制流的学习中,我们已经看到了硬件和软件是如何合作以提供基本的低层异常机制的。我们也看到了操作系统如何利用异常来支持进程上下文切换的异常控制流形式。在本节中,我们将研究一种更高层的软件形式的异常,称为 Linux 信号,它允许进程和内核中断其他进程。

一个信号就是一条小消息,它通知进程系统中发生了一个某种类型的事件。比如,图 8-26 展示了 Linux 系统上支持的 30 种不同类型的信号。

每种信号类型都对应于某种系统事件。低层的硬件异常是由内核异常处理程序处理的,正常情况下,对用户进程而言是不可见的。信号提供了一种机制,通知用户进程发生了这些异常。比如,如果一个进程试图除以 0,那么内核就发送给它一个 SIGFPE 信号(号码 8)。如果一个进程执行一条非法指令,那么内核就发送给它一个 SIGILL 信号(号码 4)。如果进程进行非法内存引用,内核就发送给它一个 SIGSEGV 信号(号码 11)。其他信号对应于内核或者其他用户进程中较高层的软件事件。比如,如果当进程在前台运行时,你键入 Ctrl+C(也就是同时按下 Ctrl 键和 C 键),那么内核就会发送一个 SIGINT 信号(号码 2)给这个前台进程组中的每个进程。一个进程可以通过向另一个进程发送一个 SIGKILL 信号(号码 9)强制终止它。当一个子进程终止或者停止时,内核会发送一个 SIGCHLD 信号(号码 17)给父进程。

序号 名称 默认行为 相应事件
1 SIGHUP 终止 终端线挂断
2 SIGINT 终止 来自键盘的中断
3 SIGQUIT 终止 来自键盘的退出
4 SIGILL 终止 非法指令
5 SIGTRAP 终止并转储内存① 跟踪陷阱
6 SIGABRT 终止并转储内存① 来自 abort 函数的终止信号
7 SIGBUS 终止 总线错误
8 SIGFPE 终止并转储内存① 浮点异常
9 SIGKILL 终止② 杀死程序
10 SIGUSR1 终止 用户定义的信号 1
11 SIGSEGV 终止并转储内存① 无效的内存引用(段故障)
12 SIGUSR2 终止 用户定义的信号 2
13 SIGPIPE 终止 向一个没有读用户的管道做写操作
14 SIGALRM 终止 来自 alarm 函数的定时器信号
15 SIGTERM 终止 软件终止信号
16 SIGSTKFLT 终止 协处理器上的栈故障
17 SIGCHLD 忽略 一个子进程停止或者终止
18 SIGCONT 忽略 继续进程如果该进程停止
19 SIGSTOP 停止直到下一个 SIGCONT② 不是来自终端的停止信号
20 SIGTSTP 停止直到下一个 SIGCONT 来自终端的停止信号
21 SIGTTIN 停止直到下一个 SIGCONT 后台进程从终端读
22 SIGTTOU 停止直到下一个 SIGCONT 后台进程向终端写
23 SIGURG 忽略 套接字上的紧急情况
24 SIGXCPU 终止 CPU 时间限制超出
25 SIGXFSZ 终止 文件大小限制超出
26 SIGVTALRM 终止 虚拟定时器期满
27 SIGPROF 终止 剖析定时器期满
28 SIGWINCH 忽略 窗口大小变化
29 SIGIO 终止 在某个描述符上可执行 I/O 操作
30 SIGPWR 终止 电源故障

图 8-26 Linux 信号

注:

① 多年前,主存是用一种称为磁芯存储器(core memory)的技术来实现的。“转储内存”(dumping core)是一个历史术语,意思是把代码和数据内存段的映像写到磁盘上。

② 这个信号既不能被捕获,也不能被忽略。

(来源:man 7 signal。数据来自 Linux Foundation。)