A signal may be blocked, which means that it will not be delivered
until it is later unblocked. Between the time when it is generated
and when it is delivered a signal is said to be pending.
信号可以被阻塞,除非阻塞被解除否则不能将信号传递给进程。从信号产生到信号被解除
阻塞这一段时间称之为挂起。
Each thread in a process has an independent signal mask, which
indicates the set of signals that the thread is currently blocking.
进程内的每个线程都有一个独立的信号掩码,信号掩码是一组信号集合,表明当前线程
阻塞的信号。
Linux提供了一个新的数据结构用来实现信号掩码的功能:信号集。多个信号组成的集合被称为信号集,其数据类型为sigset_t。在Linux的实现中,sigset_t类型是位掩码,每一个比特代表一个信号。
相关操作接口包括信号集初始化、添加、删除、设置信号掩码等:
sigemptyset, sigfillset, sigaddset, sigdelset, sigismember
sigprocmask, pthread_sigmask
#include <signal.h>
/**
* 初始化一个空的未包含任何信号的信号集。
* 成功返回0,失败返回-1并置errno
*/
int sigemptyset(sigset_t *set);
/**
* 初始化一个包含任何信号的信号集。
* 成功返回0,失败返回-1并置errno
*/
int sigfillset(sigset_t *set);
/**
* 向信号集中添加一个信号。
* 成功返回0,失败返回-1并置errno
*/
int sigaddset(sigset_t *set, int signum);
/**
* 从信号集中删除一个信号。
* 成功返回0,失败返回-1并置errno
*/
int sigdelset(sigset_t *set, int signum);
/**
* 判断该信号是否在信号集中
* 属于返回1,不属于返回0,出错返回-1并置errno
*/
int sigismember(const sigset_t *set, int signum);
/**
* 将当前线程的信号集读取到set结构体中
* 成功返回0,失败返回-1并置errno
*/
int sigpending(sigset_t *set);
Glibc扩展函数
如果定义了 _GNU_SOURCE 宏,signal.h还提供了额外三个参数用于操作信号集,不过
这些都是非标准的函数(其它系统可能有类似的实现),不能用于移植程序的开发中
/**
* 判断信号集是否为空
* 为空返回1,否则返回0
*/
int sigisemptyset(const sigset_t *set);
/**
* 取left 和 right的并集,并存储到dest结构体中
* 成功返回0,失败返回-1并置errno
*/
int sigorset(sigset_t *dest, const sigset_t *left,
const sigset_t *right);
/**
* 取left 和 right的交集,并存储到dest结构体中
* 成功返回0,失败返回-1并置errno
*/
int sigandset(sigset_t *dest, const sigset_t *left,
const sigset_t *right);
/**
* 获取或设置进程的阻塞信号掩码
*
* 根据参数how的值,提供了三种用于改变进程的阻塞信号掩码方式
*
* SIG_BLOCK:新的进程信号掩码是当前信号掩码与set指向信号集的并集,相当于在当前信号集
* 掩码中增加set的信号。
*
* SIG_UNBLOCK: 新的进程信号掩码是当前信号掩码与set指向信号集的补集的交集,相当于从
* 当前信号掩码中删除set中信号,解除对其的屏蔽。
*
* SIG_SETMASK : 直接把进程的信号掩码设置成set指向的信号集。
*
* 如果参数oldset不为NULL,之前的信号掩码配置将会存储到该指针中。
* 如果参数set为NULL的话,相当于不做任何改变。
*
* 另外多线程中使用该函数的结果将是未定义的,多线程中最好使用pthread_sigmask()接口
*
* 成功返回0,失败返回-1并置errno
*/
#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
/**
* 该函数功能和sigprocmask一样,只不过是用在多线程中,用于改变调用线程的信号掩码集。
*
* 成功返回0,失败返回错误码,编译链接的时候加上-pthread选项。
*/
#include <signal.h>
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
参考资料
1. 《Linux环境编程,从应用到内核》高峰,李彬著
2. man signal : http://www.man7.org/linux/man-pages/man7/signal.7.html
man sigsetops : http://www.man7.org/linux/man-pages/man3/sigsetops.3.html