6. 信号的阻塞处理
1. 信号掩码——被阻塞的信号集
每个进程都有一个用来描述哪些信号传送来将被阻塞的信号集,如果某种信号在某个进程的阻塞信号集中,
则传送到该进程的此种信号将会被阻塞。 当前被进程阻塞的信号集也叫信号掩码,类型为sigset_t。
每个进程都有自己的信号掩码,且创建子进程时,子进程会继承父进程的信号掩码。
2. 信号阻塞和忽略的区别
阻塞的概念与忽略信号是不同的:操作系统在信号被进程解除阻塞之前不会将信号传递出去,被阻塞的信号也不会影响进程的行为,
信号只是暂时被阻止传递;当进程忽略一个信号时,信号会被传递出去,但进程将信号丢弃。
3. 信号集的操作
信号集可以由以下几个函数操作:
int sigemptyset(sigset_t *set); //清空信号集
int sigfillset(sigset_t *set); //将所有信号填充进set中
int sigaddset(sigset_t *set, int signum); //往set中添加信号signum
int sigdelset(sigset_t *set, int signum); //从set中移除信号signum
int sigismember(const sigset_t *set, int signum); //判断signnum是不是包含在set中,在返回1,不在返回0
初始化往往可以用sigemptyset()将信号集清空,再用sigaddset()向信号集中添加信号;或者可以使用sigfillset()
将所有信号添加到信号集,再用sigdelset()将某信号从中删除掉。
int sigpending(sitset_t *set);// 获取未决信号,未决信号指信号产生到被进程处理之前的状态。set 输出参数,
处于未决状态的信号集。0,调用成功,-1,调用失败。
int sigsuspend(const sigset_t *set); set输入参数,表示阻塞信号集。其工作过程如下:
A.设置进程的信号掩码并阻塞进程
B.收到信号,恢复原来的信号掩码
C.调用那个进程设置的信号处理函数
D.等待信号处理函数返回,sigsuspend返回。
四步操作一次性完成,保证其原子性。
int sigqueue(pid_t pid, int signum, union sigval val);发送信号,同时附加数据。
union sigval 结构
typedef union sigval{
int sigval_int;
void * sigval_ptr;
}sigval_t;
pid: 目的进程ID
signum:要发送的信号,例如:SIGINT
val: 附加的信息,为int或者void * 指针。
例:sigval_t val.sigval_ptr="this is the message";
sigqueue(getpid(),SIGINT,val);为向自己发送SIGINT信号,附加数据val
4. sigprocmask()介绍
可以使用函数sigprocmask()来检查或者修改进程的信号掩码。函数信息如下:
#include <signal.h>
int sigprocmask ( int how, const sigset_t *restrict set,sigset_t *restrict old );
参数how 是一个整数,说明信号掩码的修改方式:
SIG_BLOCK 将set指向的信号集中的信号添加到当前阻塞信号集中;
SIG_UNBLOCK 从当前阻塞信号集中移除set指向的信号集中的信号;
SIG_SETMASK指定set所指向的信号集为当前阻塞信号集。
此外,如果参数set为NULL, 说明不需要修改,如果old 为NULL,sigprocmask会将修改之前的信号集放在*old 之中返回。
例子: