前言
在 Linux 系统中,进程信号是一套高效的'异步通信机制',如同给进程发送的'通知',能够打断进程的正常执行流程,触发预设的处理动作。小到 Ctrl+C 终止前台进程,大到异常崩溃时的核心转储(Core Dump)、进程间的紧急通知,信号贯穿了 Linux 进程管理的方方面面。
信号的本质是内核向进程传递事件的'软件中断',其生命周期涵盖'产生→发送→保存→递达→处理'五大环节,背后依赖 Block(阻塞)、Pending(未决)、Handler(处理函数)三张核心表的协同工作。本文将从基础认知出发,层层拆解进程信号的核心逻辑:先讲信号的三种处理方式、前台/后台进程与信号的关联,再深入信号捕获的 signal 系统调用、键盘输入触发信号的底层原理;随后详解信号的五种产生途径(键盘、命令、系统调用、异常、软件条件),并剖析内核中信号的保存机制与阻塞/未决状态的核心概念;最后结合 Core Dump 调试、信号位图管理等实操技巧,帮读者打通'理论原理'与'实际应用'的壁垒。
信号的初步认识
- 进程必须要能识别和处理信号——就算这个信号没有被产生,进程也需要具备处理这个信号的能力。对信号的处理能力,属于进程的内置功能。
- 进程没有收到信号,也能知道这些信号的处理方法是什么。
- 当进程真的收到了信号,进程可能不会立马处理这个信号,而是等到合适的时候处理。
- 进程具有临时保存哪些信号发生了的能力。因为信号产生到信号被处理之间会有时间窗口。
信号的处理方式有三种(只能三选一):
- 默认动作
- 忽略
- 自定义动作(比如:捕捉这个信号)
在 Linux 中,一次登录就会有一个终端,一个终端一般只有一个 Bash;一个 Bash 的话就只允许一个进程是前台进程,但是可以有多个进程是后台进程。这样的话算两次登录。把进程搞成后台运行的方法:最后加个 &,例如 ./a.out &。
注意:只有前台进程才能获取键盘输入,前台进程搞成其他了的话,Bash 就用不了了。
Ctrl+C 只能杀掉前台进程,不能杀后台进程。
捕获信号的办法
1 到 31 的信号称为普通信号(掌握这些就行了),后面的称为实时信号。
例如:SIGHUP 这些是宏,其实就是 1。
想要知道这些信号是干啥用的:man 7 signal 可以查询,例如信号的默认处理动作。
这个系统调用接口可以用来捕捉信号,程序里只需要设置一次,往后都有效(但是进程结束了也就没了)。
这里的 handler 是用来修改特定进程对于信号的处理动作的,也可以设置成例如 SIG_IGN 这样的(这是信号处理动作的宏定义)。信号处理动作的宏定义:
SIG_IGN:忽略该信号SIG_DFL:使用系统默认的信号处理动作 也就是用来改当前进程的 handler 表。
使用方法: 注意:不是所有信号都能被 signal 捕捉到的,在普通信号里面 9 号和 19 号是不行的。
键盘数据输入给内核的原理
键盘上有按键输入时会产生硬件中断(通过中断号和中断单元通知 CPU),CPU 通过中断向量表找到处理问题的方法,然后 OS 就会接管并执行对应的处理中断的程序。
这个中断向量表是 OS 维护的,里面存的是处理中断的那些方法的地址。
执行中断的程序:例如 Ctrl+C 这种特殊组合键,就被 OS 处理成了信号。
直接访问外设的方式,主要是磁盘、显示器、键盘。 CPU 保存数据的原理:给寄存器的针脚发送高低电平信号。 信号其实就是用软件方式,对进程模拟的硬件中断(但不是真的硬件中断)。
引申:键盘回显到显示器,如果显示器上还要其他数据显示,是不会打乱输入的: 因为键盘的输入是存在自己的缓冲区里面的,只是把这部分数据拷贝了一份给显示器的缓冲区而已。 不同的文件会使用不同的缓冲区。
Core Dump
Core Dump(核心转储):用法:开启 gdb 调试器之后,core-file core.pid 文件,然后就会给出出错行是哪个以及报错的信息。
SIGINT 和 SIGQUIT 的区别就是 SIGQUIT 除了终止进程,还会 Core Dump。
一个进程异常终止时,如果信号的 Action 是 Core 的话,OS 会将进程在内存中的运行信息转储到进程的当前目录(和进程同一级)里面形成 core.pid 文件,例如 core.30238。 是 Core 的话,进程状态那个 Core Dump 那个位置就是 1。
在默认情况下,云服务器的 Core 功能是关闭的,害怕挂起之后又运行,这样就会产生很多个 core.pid 文件,这个文件的大小又很大。
一些相关的指令:
ulimit -a:列出当前用户所有的进程资源限制配置(例如:核心转储文件大小的限制)。
ulimit -c:显示核心转储文件大小的限制。
ulimit -c m:把核心转储文件大小的限制改成 m(例如 1024),改成非 0 的,也就开启了 Core 功能。


