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