信号的其它特性
【摘自《Linux/Unix系统编程手册》】
核心转储文件
特定信号会引发进程创建一个核心转储文件并终止运行。所谓核心转储是内含进程终止时内存映像的一个文件。将该内存映像加载到调试器中,即可查明信号到达时程序代码和数据的状态。
从 Linux 版本 2.6 开始,可以根据 Linux 特有的 /proc/sys/kernel/core-pattern 文件所包含的格式化字符串来控制对系统上生成的所有核心转储文件的命名。默认情况下,该文件所含字符串为 core。特权级用户可以将该文件内容定义为下表中所列的人一个是说明符,待实际命名时再以表中右列所示相应值加以替换。此外,允许字符串中包含斜线(/),换言之,字符串不仅包含核心文件的名称,还包括核心文件的所在(绝对或相对)目录。替换所有格式说明符后,由此生成的路径名字符串长度至多可达 128 个字符,超出部分将被截断。
说 明 符 | 替 代 为 |
%c | 对核心文件大小的资源软限制(字节数;始于 Linux 2.6.24) |
%e | 可执行文件名(不含路径前缀) |
%g | 遭转储进程的实际组 ID |
%h | 主机系统的名称 |
%p | 遭转储进程的进程 ID |
%s | 导致进程终止的信号编号 |
%t | 转储时间,始于Epoch,以秒为单位 |
%u | 遭转储进程的实际用户 ID |
%% | 单个 % 字符 |
信号的同步生成和异步生成
进程一般无法预测其接受信号的时间,这里的信号属于异步生成,即引发信号产生(无论信号发送者是内核还是另一进程)的事件,其发生与进程的执行无关。
然而,有时信号的产生是由进程本身的执行造成的,例如使用 raise()、kill() 或者 killpg() 向自身发送信号,这种情况下,信号的产生就是同步的——会立即传递信号(除非该信号遭到阻塞),其传递不但可以预测,而且可以重现。
注意,同步是对信号产生方式的描述,并不针对信号本身。所有的信号既可以同步产生,也可以异步产生。
信号传递的时机与顺序
- 何时传递一个信号?
同步产生的信号会立即传递。例如,硬件异常时会触发一个即时信号,而当进程使用 raise() 向自身发送信号时,信号会在 raise() 调用返回前就已经发出。
当异步产生一个信号时,即时并未将其阻塞,在信号产生和实际传递之间仍可能会存在一个(瞬时)延迟。在此期间,信号处于等待状态。这是因为内核将等待信号传递给进程的时机是,该进程正在执行,且发生由内核态 到用户态的下一次切换时。实际上,这意味着在以下时刻才会传递信号:
1. 进程在前度超时后,再度获得调度时(即,在一个时间片的开始处)
2. 系统调用完成时(信号的传递可能引起正在阻塞的系统调用过早完成)
- 解除对多个信号的阻塞时,信号的传递顺序
如果进程使用 sigprocmask() 解除了对多个等待信号的阻塞,那么所有这些信号会立即传递给该进程。
就目前的 Linux 实现而言,Linux 内核按照信号编号的升序来传递信号。例如,如果对处于等待状态的信号 SIGINT(信号编号2)和 SIGQUIT(信号编号3)同时解除阻塞,那么无论这两个信号的产生次序如何,SIGINT 都将先于 SIGQUIT 而传递。然而,也不能对传递(标准)信号的特定顺序产生任何依赖,因为 SUSv3 规定,多个信号的传递顺序由系统实现决定。(该条款仅适用于标准信号)
当多个解除了阻塞的信号正在等待传递时,如果在信号处理器函数执行期间发生了内核态和用户态之间的切换,那么将中断此处理器函数的执行,转而调用第二个信号处理器函数(如此递进)