我们需要一个数据类型来表示多个信号--一个信号集。我们在函数比如sigprocmask(下节)里使用它来告诉内核不允许这个集里的任何信号发
生。正如我们之前提到的,不同信号的数量可以超过整型的位数,所以一般来说,我们不能用一个整型来以为个信号一位的方式表示。POISX.1定义了数据类
型sigset_t来包含一个信号集,下面的5个函数用来操作信号集。
- #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初始化信号集以便所有的信号被包含。所有的应用都必须为每
个信号集调用一次sigemptyset或sigfillset,在使用信号集之前,因为我们不假定C对外部和静态变量的0的初始化对应于一个给定系统上
的信号集的实现。
一旦我们初始化了一个信号集,我们可以加上或删除集里指定的信号。函数sigaddset向一个已存在的集合加入一个信号,而sigdelset从一个信号删除一个信号。在所有接受一个信号集为参数的函数里,我们总是传入信号集的地址作为参数。
实现
如
果实现比一个整型位数更少的信号,那么一个信号集可以用每个信号一位的方式实现。在本节后面,假定一个实现有31个信号和32位的整型。
sigemptyset函数对这个整型清零,而sigfillset函数打开这个整型里的所有位。这两个函数可以实现为
头文件里的宏:
#define sigemptyset(ptr) (*(ptr) = 0)
#define sigfillset(ptr) (*(ptr) = ~(sigset_t)0, 0)
注意sigfillset必须返回0,除了打开信号集里的所有位,所以我们使用C的逗号操作符,它返回逗号后的值作为表达式的值。
使用这个实现,sigaddset打开一个信号位而sigdelset关闭一个信号位。sigismember测试一个特定的位。因为没有信号被编号为0,我们把信号号减1来得到执行的位。下面的代码展示了这些函数的实现:
- #include <errno.h>
- /* <signal.h usually defines NSIG to include signal number 0 */
- #define NSIG 32
- #define SIGBAD(signo) ((signo) <= 0 || (signo) >= NSIG)
- typedef int sigset_t;
- 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);
- }
我们可能想把这三个函数作为
头文件里的单行的宏,但是POSIX.1要求我们检查信号号参数来验证并在它无效时设置errno。在宏里这样做比在一个函数里更难。
阅读(831) | 评论(0) | 转发(0) |