1.信号阻塞集
信号阻塞集也称信号屏蔽集、信号掩码。每个进程都有一个阻塞集,创建子进程时子进程将继承父进程的阻塞集。信号阻塞集用来描述哪些信号递送到该进程的时候被阻塞(在信号发生时记住它,直到进程准备好时再将信号通知进程)。
所谓阻塞并不是禁止传送信号, 而是暂缓信号的传送。若将被阻塞的信号从信号阻塞集中删除,且对应的信号在被阻塞时发生了,进程将会收到相应的信号。
我们可以通过 sigprocmask() 修改当前的信号掩码来改变信号的阻塞情况。
函数原型:
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
功能: 检查或修改信号阻塞集,根据 how 指定的方法对进程的阻塞集合进行修改,新的信号阻塞集由 set 指定,而原先的信号阻塞集合由 oldset 保存。
参数: how: 信号阻塞集合的修改方法,有 3 种情况:
set: 要操作的信号集地址。若 set 为 NULL,则不改变信号阻塞集合,函数只把当前信号阻塞集合保存到 oldset 中。
oldset: 保存原先信号阻塞集地址。
返回值: 成功:0 失败:-1,失败时错误代码只可能是 EINVAL,表示参数 how 不合法。
注意:不能阻塞SIGKILL和SIGSTOP等信号,但是当 set 参数包含这些信号时 sigprocmask() 不返回错误,只是忽略它们。另外,阻塞 SIGFPE 这样的信号可能导致不可挽回的结果,因为这些信号是由程序错误产生的,忽略它们只能导致程序无法执行而被终止。
实例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
int main(int argc, char *argv[])
{
sigset_t set; // 信号集合
int i = 0;
sigemptyset(&set); // 清空信号集合
sigaddset(&set, SIGINT); // SIGINT 加入 set 集合
while(1)
{
// set 集合加入阻塞集,在没有移除前,SIGINT 会被阻塞
sigprocmask(SIG_BLOCK, &set, NULL);
for(i=0; i<5; i++)
{
printf("SIGINT signal is blocked\n");
sleep(1);
}
// set 集合从阻塞集中移除
// 假如 SIGINT 信号在被阻塞时发生了
// 此刻,SIGINT 信号立马生效,中断当前进程
sigprocmask(SIG_UNBLOCK, &set, NULL);
for(i=0; i<5; i++)
{
printf("SIGINT signal unblocked\n");
sleep(1);
}
}
return 0;
}
运行结果:
[root@iz2zefozq9h39txdb8s7npz shelldemo]# ./a.out
SIGINT signal is blocked
SIGINT signal is blocked
SIGINT signal is blocked
^CSIGINT signal is blocked
SIGINT signal is blocked