信号的内核结构
(注意:子进程会继承父进程的信号的屏蔽和排列)
在进程的PCB中会有关于信号的模块,当一个进程发出某个信号后,会被操作系统拿到,操作系统又会给对应的PCB,然后PCB根据第几号信号在block(屏蔽)信号集中查看是否上锁,并把pending(未决)信号集里的对应位置置为1。如果block信号集没有锁,那就直接去sighand(信号处理)里找对用的操作,如果这个信号里边写的就是SIG_DFL就是默认操作,SIG_IGN忽略这个信号,如果是个函数指针的话,就是指定了信号处理动作,那么就去执行这个函数。
如果block信号集是1锁了的话,pending信号集还是会置为1,然后如果block解锁后就可以执行了。
信号集&信号屏蔽集
从上图知,每个信号只有一个bit的未决标志,非0即1,不记录该信号产生了多少次,阻塞标志也是这样表示的。
因此,未决和阻塞标志可以用相同的数据类型sigset_t来存储,sigset_t称为信号集,这个类型可以表示每个信号的“有效”或“无效”状态;
在阻塞信号集中“效”和“无效”的含义是该信号是否被阻塞;
而在未决信号集中“有效”和“无效”的含义是该信号是否处于未决状态。
阻塞信号集也叫做当前进程的信号屏蔽字(Signal Mask),这里的“屏蔽”应该理解为阻塞而不是忽略
sigprocmask函数
sigprocmask函数用来更改信号内核,来设置是否屏蔽/解锁某一些信号
#include<signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
参数1how:共有3个关键字
SIG_BLOCK //上锁,
SIG_UNBLOCK //解锁,
SIG_SETMSASK
//不管之前是什么屏蔽信号集,现在用指定的这个信号屏蔽集。一般搭配第三个参数使用
参数2:信号集的地址指针。
如果参数1是SIG_BLOCK的话,即我们希望把这个信号屏蔽集中的信号加入到原本的屏蔽集中去,即mask = mask | set。
如果参数1是SIG_UNBLOCK,那么就是希望从原本的信号屏蔽集中去除这个屏蔽集中的信号。做mask = mask & ~set。
参数3:是返回的旧的mask,当第一个参数为SET_SETMASK时,第三个参数为之前上锁时候的返回值,&old_set,一般不用就写NULL。
信号集
s