10.12 sigprocmask函数
在10.8节中我们提到进程的掩码是一个当前阻塞信号发送到进程的信号集合。一个进程可以查看其信号掩码,改变其信号掩码,或者同时执行这两个操作,通过调用函数sigprocmask来实现上述要求.
#include <signal.h>
int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
return:0 if OK, -1 on error.
首先,如果oset是一个非空指针,那么当前进程的信号掩码将会通过oset返回.
其次,如果set是一个非空指针,参数how显示了当前信号掩码被修改的方式,图10.13讲述了参数how的可能取值。SIG_BLOCK是一个或操作,而SIG_SETMASK是一个赋值操作,注意SIGKILL与SIGSTOP不可以被阻塞。
how | Description |
---|---|
SIG_BLOCK | 新的信号掩码是当前信号掩码与set指定的信号集合的组合。即是说,set包含了我们想阻塞的额外的信号. |
SIG_UNBLOCK | 新的信号掩码是当前信号掩码与set信号集合的补集的交集,也就是说,set包含了我们想要接触阻塞的信号. |
SIG_SETMASK | 新的信号将会被set传入的信号集替换。 |
Figure 10.13 使用函数sigprocmask改变当前信号掩码的方法
如果set是一个空指针,那么进程的信号掩码就不会被改变,参数how也将被忽略。
在调用函数sigprocmask以后,如果有任何未被阻塞的信号被挂起,那么这些信号中至少有一个信号会在sigprocmask返回之前被发送到进程。
函数sigprocmask只是为单线程进程定义的,对于多线程进程,系统提供了另外一个函数来操作线程的信号掩码,关于此,我们将在12.8中进行讨论。
Example
图10.14 中的函数用于打印调用进程的信号掩码中的名称,我们将在图10.20以及10.22中的程序中调用该函数.
#include "apue.h"
#include <errno.h>
void pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /*we can be called by signal handlers*/
if(sigprocmask(0, NULL, &sigset)<0)
{
err_ret("sigprocmask error");
}
else
{
printf("%s", str);
if(sigismember(&sigset, SIGINT))
printf(" SIGINT");
if(sigismember(&sigset, SIGQUIT))
printf(" SIGQUIT");
if(sigismember(&sigset, SIGUSR1))
printf(" SIHUSR1");
if(sigismember(&sigset, SIGALRM))
printf(" SIGALRM");
/*remaining signals can go here */
printf("\n");
}
errno = errno_save; /*restore errno*/
}