每个进程都有一个用来描述哪些信号传送来将被阻塞的阻塞的信号集,如果某种信号在某个进程的阻塞信号集中,则传送到该进程的此种信号将会被阻塞。信号阻塞操作主要有以下三个函数:
#include<signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
int sigpending(sigset_t *set);
int sigsuspend(const sigset_t *mask);
sigprocmask系统调用用于改变当前阻塞信号集,它具体的功能主要取决于第一个参数how。how的取值如下:
-----------------------------------------------------------------------------------------------------
参数how | 动作
------------------------------------------------------------------------------------------------------
SIG_BLOCK | 将set指向的信号集中的信号添加到当前阻塞信号集中
------------------------------------------------------------------------------------------------------
SIG_UNBLOCK | 从当前阻塞信号集中移除set指向的信号集中的信号,
| 移除一个阻塞信号集中不存在的信号那也是合法的
------------------------------------------------------------------------------------------------------
SIG_SETMASK | 指定set所指向的信号集为当前阻塞信号集
--------------------------------------------------------------------------------------------------------
如果sigprocmask的第三个参数oldset非空,则oldset保存旧的信号阻塞集。
sigpending(…)获得当前已传送到进程,却被阻塞的所有信号,在set指向的信号集中保存未决(阻塞)的信号。
sigsuspend(const sigset_t
*mask),
在接收到某个信号之前,临时用mask替换进程的信号掩码,并挂起进程,直到收到信号为止。sigsuspend返回后,即系统在接受到信
号后,进程将恢复调用前的信号掩码,调用信号处理函数完毕后进程将继续执行。始终返回-1,并将errno设置为EINTR。
下面这个小程序测试了信号的阻塞以及信号集操作:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#define BLOCK_SIG SIGRTMIN+10
/*信号处理函数*/
static void sig_handler(int signum,struct siginfo *sig_info,void *unused)
{
printf("\n<! receive signal %d !>\n",signum);
printf("-----------------< Signal information >--------------------\n");
printf("\tsi_signo :\t%d\n",sig_info->si_signo);//信号值
printf("\tsi_errno :\t%d\n",sig_info->si_errno);//error值
printf("\tsi_code :\t%d\n",sig_info->si_code); //信号产生的原因
printf("\tsi_int :\t%d\n",sig_info->si_int); //4 bytes 整型
}
int main(int argc,char**argv)
{
sigset_t new_mask,old_mask,pending_mask;
struct sigaction act;
printf("Block precess PID : %d\n",getpid());
/*
*设置struct sigaction结构
*/
sigemptyset(&act.sa_mask);
act.sa_flags=SA_SIGINFO;
act.sa_sigaction=(void *)sig_handler;
/*
*安装信号
*/
if(sigaction(BLOCK_SIG,&act,NULL))
printf("install siganl SIGRTMIN+10 error!\n");
/*
*设置新的屏蔽信号集,阻塞 SIGRTMIN+10 信号!
*/
sigemptyset(&new_mask);
sigaddset(&new_mask,BLOCK_SIG);
if(sigprocmask(SIG_BLOCK,&new_mask,&old_mask))
printf("block signal SIGRTMIN+10 error!\n");
sleep(30);//等待信号SIGRTMIN+10唤醒,但因为上面设置了此信号阻塞,因此此处不能从睡眠中唤醒进程
printf("\nNow begin to get pending mask and unblock SIGRTMIN_10\n");
sigpending(&pending_mask); //获得当前已传送到进程,却被阻塞的所有信号
if(sigismember(&pending_mask,BLOCK_SIG))
printf("\nsignal SIGRTMIN+10 is pending!\n");
/*
*恢复原来的信号屏蔽集,此前被阻塞的信号触发
*/
sigprocmask(SIG_SETMASK,&old_mask,NULL);
printf("\nsignal unblocked!\n");
/*
*进程进入睡眠,直到有信号唤醒进程,或时间到!
*/
sleep(30);
exit(0);
}
配合上篇中介绍的信号发送小程序,你可以测试一下程序的执行结果!