Linux 信号

Linux 系统提供了一种进程间异步通信的方式 —— 信号(signal)。信号可认为是一种软中断机制,许多重要的程序都需要处理信号。例如,在终端输入 Ctrl + C 快捷键可以中断程序,实际上就是给该进程发送了一个 SIGINT 信号。

信号类型

Linux 系统一共定义了 64 种信号,分为两大类:可靠信号与不可靠信号,前 32 种信号为不可靠信号,后 32 种为可靠信号。

  • 不可靠信号:也称为非实时信号,不支持排队,信号可能会丢失,发送多次相同的信号,进程只能收到一次,信号值取值区间为 1~31;
  • 可靠信号:也称为实时信号,支持排队,信号不会丢失,发多少次,就可以收到多少次。信号值取值区间为 32~64。

在 Linux 系统中,可以通过 kill -l 命令查看所有 signal 信号,下表列出了 1~31 的信号及其描述。

信号值 信号名 描述 备注
1 SIGHUP 挂起
2 SIGINT 中断
3 SIGQUIT 退出
4 SIGILL 非法指令
5 SIGTRAP 断点或陷阱指令
6 SIGABRT abort 发出的信号
7 SIGBUS 非法内存访问
8 SIGFPE 浮点异常
9 SIGKILL kill 信号 不能被忽略、处理和阻塞
10 SIGUSR1 用户信号1
11 SIGSEGV 无效内存访问
12 SIGUSR2 用户信号2
13 SIGPIPE 管道破损,没有读端的管道写数据
14 SIGALRM alarm 发出的信号
15 SIGTERM 终止信号
16 SIGSTKFLT 栈溢出
17 SIGCHLD 子进程退出 默认忽略
18 SIGCONT 进程继续
19 SIGSTOP 进程停止 不能被忽略、处理和阻塞
20 SIGTSTP 进程停止
21 SIGTTIN 进程停止,后台进程从终端读数据时
22 SIGTTOU 进程停止,后台进程想终端写数据时
23 SIGURG I/O 有紧急数据到达当前进程 默认忽略
24 SIGXCPU 进程的 CPU 时间片到期
25 SIGXFSZ 文件大小的超出上限
26 SIGVTALRM 虚拟时钟超时
27 SIGPROF profile 时钟超时
28 SIGWINCH 窗口大小改变 默认忽略
29 SIGIO I/O 相关
30 SIGPWR 关机 默认忽略
31 SIGSYS 系统调用异常

信号处理

Linux 信号的处理有三种方法,分别是:忽略、捕捉和默认动作

  • 忽略信号:大多数信号可以使用这个方式来处理,但是有两种信号不能被忽略(分别是 SIGKILLSIGSTOP)。因为这两中信号向内核和超级用户提供了进程终止和停止的可靠方法,如果忽略了,那么这个进程就变成了没人能管理的进程,显然是内核设计者不希望看到的场景。
  • 捕捉信号:需要告诉内核,用户希望如何处理某一种信号。也就是说用户需要写一个信号处理回调函数,然后将这个函数告诉内核。当该信号产生时,由内核来调用用户自定义的函数,以此来实现某种信号的处理。
  • 系统默认动作,对于每个信号来说,系统都对应由默认的处理动作,当发生了该信号,系统会自动执行。不过,对系统来说,大部分的处理方式都比较粗暴,就是直接杀死该进程。

具体的信号默认动作可以使用 man 7 signal 来查看系统的具体定义。