我们需要有一个能表示多个信号——信号集(signal set)的数据类型。

我们将在sigprocmask (下一节中说明)类函数中使用这种数据类型,以便告诉内核不允许发生该信号集中的信号。如前所述,不同的信号的编号可能超过一个整型量所包含的位数,所以一般而言,不能用整型量中的一位代表一种信号,也就是不能用一个整型量表示信号集。POSIX.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);
//4个函数返回值:若成功,返回0;若出错,返回−1
int sigismember(const sigset_t *set, int signo);
//返回值:若真,返回1;若假,返回0

函数sigemptyset初始化由set指向的信号集,清除其中所有信号。

函数sigfillset初始化由set指向的信号集,使其包括所有信号。

所有应用程序在使用信号集前,要对该信号集调用sigemptyset或sigfillset一次。这是因为C编译程序将不赋初值的外部变量和静态变量都初始化为0,而这是否与给定系统上信号集的实现相对应却并不清楚。

一旦已经初始化了一个信号集,以后就可在该信号集中增、删特定的信号。

函数 sigaddset将一个信号添加到已有的信号集中。

sigdelset 则从信号集中删除一个信号。对所有以信号集作为参数的函数,总是以信号集地址作为向其传送的参数。

实现

?: 如果实现的信号数目少于一个整型量所包含的位数,则可用一位代表一个信号的方法实现信号集。例如,本书的后续部分都假定一种实现有31种信号和32位整型。

sigemptyset函数将整型设置为0, sigfillset函数则将整型中的各位都设置为1。这两个函数可以在<signal.h>头文件中实现为宏:

#define sigemptyset(ptr) (*(ptr) = 0)
#define sigfillset(ptr) (*(ptr) = ~(sigset_t)0, 0)

注意,除了设置信号集中各位为1外,sigfillset必须返回0,所以使用C语言的逗号算符,它将逗号算符后的值作为表达式的值返回。

使用这种实现,sigaddset 开启一位(将该位设置为 1),sigdelset 则关闭一位(将该位设置为0);sigismember测试一个指定的位。因为没有信号编号为0,所以从信号编号中减1以得到要处理位的位编号数。图10-12给出了这些函数的实现。

#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);
}

图10-12 sigaddset、sigdelset和sigismember的实现

也可将这3个函数在<signal.h>中实现为各一行的宏,但是POSIX.1要求检查信号编号参数的有效性,如果无效则设置errno。在宏中实现这一点比函数要难。

results matching ""

    No results matching ""