sigprocmask(int how, const sigset_t *new_set, const sigset_t *old_set);
how有三种参数:
- SIG_BLOCK
- SIG_UNBLOCK
- SIG_SETMASK
两种实现信号的屏蔽与阻塞的方法:
法一:SIG_BLOCK, SIG_UNBLOCK成对出现
法二:SIG_BLOCK, SIG_SETMASK成对出现
原理:
在二者中间运行的代码,如果有kill或其它函数传递信号进来,将一律将new_set集合中的信号堵在外面,达到屏蔽信号的效果;
对于屏蔽的信号如何处理:
在信号屏蔽过程中出现的所有信号,不管发来了多少次,在解除屏蔽后,都将执行且
仅执行一次!
以下是经典例子:
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
//定义三个handler信号处理函数
static void sig_usr1(int signo)
{
printf("SIGUSR1 function\n");
}
static void sig_usr2(int signo)
{
printf("SIGUSR2 function\n");
}
static void sig_int(int signo)
{
printf("SIGINT function\n");
}
//取代signal(num, handler)函数
void sig_catch(int sig_no, void (*f)(int))
{
struct sigaction sa;
sa.sa_handler = f;
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaction(sig_no, &sa, (struct sigaction *) 0);
}
int main()
{
sigset_t newmask,oldmask;
sig_catch(SIGUSR1,sig_usr1);
sig_catch(SIGUSR2,sig_usr2);
sig_catch(SIGINT,sig_int);
// signal(SIGUSR1,sig_usr1);
// signal(SIGUSR2,sig_usr2);
// signal(SIGINT,sig_int);
//这里仅将SIGUSR1, SIGUSR2放入信号集合中
sigemptyset(&newmask);
sigaddset(&newmask,SIGUSR1);
sigaddset(&newmask,SIGUSR2);
//信号阻塞开始
sigprocmask(SIG_BLOCK,&newmask,&oldmask);
printf("SIGUSR is blocked\n");
//传来一堆信号
kill(getpid(),SIGUSR2);
kill(getpid(),SIGUSR1);
kill(getpid(),SIGUSR2);
kill(getpid(),SIGUSR1);
kill(getpid(),SIGUSR2);
kill(getpid(),SIGINT);
//分别用两种方法实现解除信号的阻塞
printf("=======\n");
printf("SIGUSR is unblocked\n");
//方法一
sigprocmask(SIG_UNBLOCK,&newmask,NULL);
//方法二
sigprocmask(SIG_SETMASK,&oldmask,NULL);
return 0;
}
执行结果:
SIGUSR is blocked //开始信号阻塞
SIGINT function //SIGINT不在集合中,可以被接收到
=======
SIGUSR is unblocked //解除信号阻塞
SIGUSR1 function //解除阻塞后,依次接收到两个信号,有且仅执行一次
SIGUSR2 function
/* 注意点:
SIGUSR1和SIGUSR2是系统内置的宏,在signal.h中
有且仅有这两个可以用户自定义