信号之信号集
我们需要有一个能表示多个信号——信号集(signal set)的数据类型。POSIX.1定义了数据类型sigset_t以包含一个信号集,并且定义了下列五个处理信号集的函数。
#include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set, int signo); 四个函数的返回值:若成功则返回0,若出错则返回-1 int sigismember(const sigset_t *set, int signo); 返回值:若真则返回1,若假则返回0,若出错则返回-1
函数sigemptyset初始化由set指向的信号集,清除其中所有信号。
函数sigfillset初始化由set指向的信号集,使其包括所有信号。
所有应用程序在使用信号集前,要对该信号集调用sigemptyset或sigfillset一次。这是因为C编译器将把未赋初值的外部和静态变量都初始化为0,而这是否与给定系统上信号集的实现相对应却并不清楚。
一旦初始化了一个信号集,以后就可以在该信号集中增、删特定的信号。
函数sigaddset将一个信号添加到现有集中,sigdelset则从信号集中删除一个信号。
对所有以信号集作为参数的函数,我们总是以信号集地址作为向其传送的参数。
实例
如果实现的信号数目少于一个整型量所包含的位数,则可用一位代表一个信号的方法实现信号集。我们假定一种实现有31种信号和32位整型值。
sigemptyset函数将整型量设置为0,sigfillset函数则将整型量中的各个位都设置为1。
这两个函数可以在<signal.h>头文件中实现为宏:
#define sigempty(ptr) (*(ptr) = 0) #define sigfillset(ptr) (*(ptr) = ~(sigset_t)0, 0)
注意,除了设置信号集各位为1外,sigfillset必须返回0,所以使用C语言的逗号运算符(逗号运算符是所有运算符中级别最低的),它将逗号运算符后的值作为表达式的返回值。
使用这种实现,sigaddset打开一位(将该位设置为1),sigdelset则关闭一位(将该位设置为0),sigismember测试一指定位。
因为没有编号为0的信号,所以从信号编码中减去1以得到要处理位的位编码数。
程序清单10-9 sigaddset、sigdelset和sigismember的实现
#include <signal.h> #include <errno.h> /* <signal.h> usually defines NSIG to include signal number 0 */ #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG) int sigaddset(sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } *set |= 1 << (signo - 1); /* turn bit on */ return(0); } int sigdelset(sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } *set &= ~(1 << (signo -1)); /* turn bit off */ return(0); } int sigismember(const sigset_t *set, int signo) { if (SIGBAD(signo)) { errno = EINVAL; return(-1); } return(*set & (1 << (signo - 1)) != 0); }
本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/。