信号的作用
实现inter process communication 的一种方式
区分 信号量(Semaphore) 实现锁
POSIX信号
信号名是信号序号的宏 即 #DEFINE SIGNIT 2 名字会被变成数字
https://man7.org/linux/man-pages/man7/signal.7.html
信号的发送与保存
2个N bits 的位向量, 代表N种信号
1. pending 待处理信号
2. blocked (signal mask) 屏蔽的信号
如果收到信号,就把pending对应位设置为1,重复收到同一信号后续信号没有影响
一般通过kill 函数发送信号
int kill(pid_t pid, int sig)调kill (2666, 1) ,向pid 为2666的进程发送信号1
用户进程可以互相发送信号, 内核进程可以给用户进程发送信号
但进程之间允许发送的信号是有限制的,父进程可以向子进程发送停止信号,其他进程不可以
信号的处理
处理时机
当进程从内核态转换到用户态 比如syscall返回 IO中断返回,如果有待处理信号,就处理信号
为什么这么设计
pending 和 blocked 都在PCB中,即处于内核中。我们每次检查都是完成某一次切换到内核态要完成的任务后,顺手检查信号。好处显而易见:提高效率
Q: 如果一直在用户态,那么就没法处理信号了?
理论上,如果一个进程真的能永远不出错、不调用系统接口且不被外部硬件打断,它确实无法处理信号。
但实际上这不可能,首先就是external interruption 中的时间片切换。
处理方法
result = pending & ~blocked
result 第i位为1, 那么就运行信号类型i对应的信号处理程序
信号处理程序在用户态
信号处理程序可以是操作系统的默认程序,也可以由这个进程设置自己的信号处理程序。eg. 窗口大小变化调整UI
当需要处理多个信号时,按序号从小到大依次处理
一旦处理,把对应pending位设置为1
Q: 如何重写信号处理程序的平衡灵活性和安全性
操作系统并不是允许进程重写“所有”信号的处理程序。 比如信号9 19,进程无法捕获,也无法忽略,实际上信号会发给操作系统,操作系统直接关闭。
信号与异常的关系
信号可以作为异常的配套机制
当操作系统处理一个异常,有的异常可以由操作系统独立解决(缺页异常),有的异常还需要应用程序配合(/0异常, 告诉应用程序,应用程序可以通过自己的GUI告诉用户错了;默认的处理会闪退崩溃)