关于信号
信号是事件发生时对进程的通知机制。有时也称之为软件中断。
一个(具有合适权限的)进程能够向另一进程发送信号。信号的这一用法可作为一种同步技术,甚至是进程间通信(IPC)的原始形式。进程也可以向自身发送信号。然而,发往进程的诸多信号,通常都是源于内核。引发内核为进程产生信号的各类事件如下:
- 硬件发生异常,即硬件检测到一个错误条件并通知内核,随即再由内核发送相应信号给相关进程。硬件异常的例子包括执行一条异常的机器语言指令,例如被 0 除,或者引用了无法访问的内存区域。
- 用户键入了能够产生信号的终端特殊字符。其中包括中断字符(通常是 Control-C)、暂停字符(通常是 Control-Z)。
- 发生了软件事件。例如,针对文件描述符的输出变为有效,调整了终端窗口大小,定时器到期,进程执行的 CPU 时间超限,或者该进程的某个子进程退出。
针对每个信号,都定义了一个唯一的(小)整数,从 1 开始顺序展开。<signal.h>
以 SIGxxxx
形式的符号名对这些整数做了定义。由于每个信号的实际编号随系统不同而不同,所以在程序中总是使用这些符号名。
Linux 对标准信号的编号为 1~31。然而,Linux 于 signal(7)
手册页中列出的信号名称却超出了 31 个。名称超出的原因有多种。有些名称只是其他名称的同义词,之所以定义是为了与其他 UNIX 实现保持源码兼容。其他名称虽然有定义,但却并未使用。以下列表介绍了各种信号。
名称 | 信号值 | 描述 | SUSv3 | 默认 |
---|---|---|---|---|
SIGHUP |
1 | 挂起 | * | term |
SIGINT |
2 | 终端中断 | * | term |
SIGQUIT |
3 | 终端退出 | * | core |
SIGILL |
4 | 非法指令 | * | core |
SIGTRAP |
5 | 跟踪/断点陷阱 | * | core |
SIGABRT |
6 | 中止进程 | * | core |
SIGBUS |
7(SAMP=10) | 内存访问错误 | * | core |
SIGFPE |
8 | 算术异常 | * | core |
SIGKILL |
9 | 必杀(确保杀死) | * | term |
SIGUSR1 |
10 (SA=30, MP=16) | 自定义用户信号1 | * | term |
SIGSEGV |
11 | 无效的内存引用 | * | core |
SIGUSR2 |
12 | 自定义用户信号2 | * | term |
SIGPIPE |
13 | 管道断开 | * | term |
SIGALRM |
14 | 实时定时器过期 | * | term |
SIGTERM |
15 | 终止进程 | * | term |
SIGSTKFLT |
16 (SAM=undef, P=36) | 协处理器栈错误 | term | |
SIGCHLD |
17 (SA=20, MP=18) | 终止或者停止子进程 | * | ignore |
SIGCONT |
18 (SA=19, M=25, P=26) | 若停止则继续 | * | cont |
SIGSTOP |
19 (SA=17, M=23, P=24) | 确保停止 | * | stop |
SIGTSTP |
20 (SA=18, M=24, P=25) | 终端停止 | * | stop |
SIGTTIN |
21 (M=26, P=27) | BG 从终端读取 | * | stop |
SIGTTOU |
22 (M=27, P=28) | BG 向终端写 | * | stop |
SIGURG |
23 (SA=16, M=21, P=29) | 套接字上的紧急数据 | * | ignore |
SIGXCPU |
24 (M=30, P=33) | 突破对 CPU 时间的限制 | * | core |
SIGXFSZ |
25 (M=31, P=34) | 突破对文件大小的限制 | * | core |
SIGVTALRM |
26 (M=28, P=20) | 虚拟定时器过期 | * | term |
SIGPROF |
27 (M=29, P=21) | 性能分析定时器过期 | * | term |
SIGWINCH |
28 (M=20, P=23) | 终端窗口尺寸发生变化 | ignore | |
SIGIO / |
29 (SA=23, MP=22) | I/O 时可能产生 | * | term |
SIGPWR |
30 (SA=29, MP=19) | 电量行将耗尽 | term | |
SIGSYS |
31 (SAMP=12) | 无效的系统调用 | * | core |
SIGEMT |
undef (SAMP=7) | 硬件错误 | term | |
SIGPOLL |
该表格来自于《LINUX/UNIX系统编程》
在 Linux 2.2 中,信号
SIGXCPU
、SIGXFSZ
、SIGSYS
和SIGBUS
的默认行为是终止进程,但不会产生核心转储文件。自内核 2.4 以后,Linux 实现满足了 SUSv3 的要求,这些信号不但会引发进程终止,也将生成核心转储文件。在其他几个 UNIX 实现中,对信号SIGXCPU
和SIGXFSZ
的处理方式与 Linux 2.2 相同。在其他的 UNIX 实现中,对
SIGPWR
信号的默认行为通常是将其忽略。几个 UNIX 实现(特别是 BSD 衍生系统)默认情况下将忽略
SIGIO
信号。虽然
SIGEMT
信号尚未获得任何标准的接纳,但却得到大多数 UNIX 实现的支持。然而,在其他实现中,该信号通常会导致进程终止并产生核心转储文件。SUSv1 将
SIGURG
信号的默认行为定义为终止进程,这也是一些较老 UNIX 实现的默认做法。而 SUSv2 则采用了现行规范(将其忽略)。