sigprocmask() 函数原型如下:
[C++] 纯文本查看 复制代码 #include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
该函数用来设置当前信号屏蔽,也就是说,通过该函数可以设置你想要屏蔽的信号,即被屏蔽的信号递送过来,不给予理会。函数有 3 个参数,第 3 个参数 oldset 如果是个非空指针,那么进程的当前信号屏蔽字就通过 oldset 返回,或者说在设置新的信号屏蔽字之前,我们想备份一下原来的信号集设置,那么备份方法就是指定该参数。
第 2 个参数如果是个非空指针,那么它就会依照第 1 个参数 how 的指示来修改当前的信号屏蔽字,how 有 3 种方式:
1. SIG_BLOCK
该进程新的信号屏蔽字是当前信号屏蔽字和 set 指向信号集的并集,也就是说 set 包含了我们希望阻塞的附加信号。
2. SIG_UNBLOCK
该进程的新的信号屏蔽字是当前信号屏蔽字和 set 所指向的信号集补集的交集,也就是说 set 包含了我们希望解除阻塞的信号。
3. SIG_SETMASK
该进程新的信号屏蔽字将被 set 指向的信号集的值所替代。
如果 set 是个空指针,那么不改变该进程的信号屏蔽字,而 how 的值也因此无意义。
需要注意的是,SIGKILL (9号信号)和 SIGSTOP (19号信号)不能被屏蔽,如果这样,那么该进程没法杀死,成为一个霸道进程,这是不允许的。
测试代码:
[C++] 纯文本查看 复制代码 #include <stdio.h>
#include <stdlib.h>
#include <signal.h>
char *pname;
static volatile sig_atomic_t got_sig_int = 0;
static void handler(int sig)
{
if (sig == SIGUSR1)
got_sig_int = 1;
else
printf ("%s: signal %d caught\n", pname, sig);
}
int main(int argc, char *argv[])
{
int n;
pname = argv[0];
printf ("my pid : %d\n", (long)getpid());
sigset_t block_mask;
for (n = 1; n < NSIG; n++) //所有的信号都使用同一个处理函数
(void)signal(n, handler); //忽略错误(SIGKILL 和 SIGSTOP 不会被安装)
sigfillset(&block_mask); // 屏蔽所有信号,除了 SIGKILL 和 SIGSTOP
sigprocmask(SIG_SETMASK, &block_mask, NULL);
sigset_t unblock_mask;
sigemptyset (&unblock_mask);
sigaddset (&unblock_mask, SIGUSR1);
if (sigprocmask(SIG_UNBLOCK, &unblock_mask, NULL) == -1) { //不屏蔽第 10 号信号
perror("sigprocmask");
exit (EXIT_FAILURE);
}
while(!got_sig_int) //等待第 10 号信号
continue;
printf("signal SIGUSER1 caught.\n");
return 0;
}
在一个终端窗口里运行该程序:[beyes@beyes signal]$ ./sigprocmask
my pid : 2421 接着,可以在另外一个终端窗口里用 kill 命令给该程序发送信号:[beyes@beyes ~]$ kill -1 2421
[beyes@beyes ~]$ kill -2 2421
[beyes@beyes ~]$ kill -10 2421 在上面发送第 1 和第 2 号信号时,程序不会有任何反应。但是当发送第 10 号信号时,程序就会退出,此时可以看到: |