每个进程都有一个信号掩码,它给出了当前进程想要阻塞的信号的集合,信号掩码的类型为sigset_t。注意,阻塞信号与忽略信号的概念是不同的,进程阻塞信号时,操作系统会在进程解除对该信号的阻塞之前不会将信号传递出去,但解除阻塞之后,进程还是会收到该信号的。但是进程忽略信号时,操作系统会将信号传递出去,只不过时进程在处理时将该信号忽略了而已。进程通过sigprocmask函数来阻塞一个信号,通过sigaction来忽略一个信号
对信号掩码sigset_t的操作有如下5个函数
- int sigaddset(sigset_t *set, int signo):将signo添加到set中
- int sigdelset(sigset_t *set, int signo):将signo从set中删除
- int sigemptyset(sigset_t *set):将set初始化为不包含任何信号
- int sigfillset(sigset_t *set):将set初始化为包含全部信号
- int sigismember(sigset_t *set, int signo):判断signo是否包含在set集合中
通过这5个函数,我们可以实现对sigset_t进行任意我们想要的操作
sigprocmask函数
我们通过该函数实现对信号的阻塞操作,函数原型为:
int sigprocmase(int how, const sigset_t *set, sigset_t *oset)
set参数为操作的信号集,oset参数不为空时,会返回修改之前的信号掩码,how指出修改信号掩码的方式:
- SIG_BLOCK:向当前被阻塞的信号集中添加一个信号集
- SIG_UNBLOCK:向当前被阻塞的信号中删除一个信号集
- SIG_SETMASE:将制定的信号集设置为被阻塞的信号
注意:某些信号(比如SIGSTOP和SIGKILL)是不可以被阻塞的,试图阻塞这些信号,系统会忽略这个请求而不会报告错误
sigaction函数
该函数允许调用程序检查或指定与特定信号相关的动作,原型如下:
int sigaction(int sig, const struct sigaction *act, struct sigaction oact);
参数sig用来指定动作的信号码,act用来指定要采取的动作,若该参数为NULL,则不会作改变;oact用来接受与信号相关的前一个动作。
struct sigaction{
void (*sa_handler)(int);//SIG_DEF、SIG_IGN或者指向函数的指针
sigset_t sa_mask;//处理程序在执行过程中需要阻塞的额外的信号
int sa_flags;//特殊的标志符和选项
void (*sa_sigaction) (int, siginfo_t *, void *);//实时处理程序
}
sa_handler和sa_sigaction只能有一个有效,由sa_flags字段的标志符SA_SIGINFO指出谁有效。
注意:虽然我们可以使用signal函数来注册信号处理函数,但是在支持sigaction的版本中,我们应该用sigaction函数来代替它,因为后者要更安全,功能更强大。