【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 信号集与屏蔽信号
中断是可以被屏蔽(阻塞)的(部分硬件中断是必须立即处理的,例如复位中断),因此,Linux的信号是可以屏蔽,即阻塞信号。但这与前面提到的忽略是有区别的。
信号忽略:系统仍然传递该信号,只是相应进程对该信号不作任何处理而已。
信号阻塞:系统不传递该信号,显示该进程无法接收到该信号直到进程的信号集发生改变。
sigprocmask设置进程屏蔽信号集
获取当前未决的信号
任何已经发送给进程,而没有被捕获的信号都是未决的,这包括没有来得及捕获(例如正在处理其他信号)和因为进程暂时屏蔽了这个信号而导致的未决。
sigpending()函数返回当前进程所有未决的集合。
extern int sigpending(sigset_t *_set);
信号集操作 教材251页
清空信号集
extern int sigemptyset(sigset_t *_set);
清空所有信号到信号集
extern int sigfillset(sigset_t *_set);
添加信号到信号集
extern int sigaddset(sigset_t *_set, int _signo);
从信号集中删除某个信号
extern int sigdelset(sigset_t *_set, int _signo);
检测信号是否在信号集中
extern int sigismember(_const sigset_t *_set, int signo);
检测信号集是否为空信号集
extern int sigisemptyset(_const sigset_t *_set);
示例程序:
1. 信号集存储结构
示例代码:
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
int output(sigset_t set);
int main()
{
sigset_t set;
printf("after empty the set:\n");
sigemptyset(&set);
output(set);
printf("after add signo=2:\n");
sigaddset(&set,2);
output(set);
printf("after add signo=10:\n");
sigaddset(&set,10);
output(set);
sigfillset(&set);
printf("after fill all:\n");
output(set);
return 0;
}
int output(sigset_t set)
{
int i=0;
for(i=0;i<1;i++) //can test i<32
{
printf("0x%8x\n",set.__val[i]);
if((i+1)%8==0)
printf("\n");
}
}
运行结果:
$ ./a.out
after empty the set:
0x 0
after add signo=2:
0x 2
after add signo=10:
0x 202
after fill all:
0x7fffffff
2. 进程屏蔽信号应用示例
示例代码:
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
static void sig_quit(int);
int main(int argc,char *argv[])
{
sigset_t newmask, oldmask, pendmask;
if (signal(SIGQUIT, sig_quit) == SIG_ERR)
{
perror("signal");
exit(EXIT_FAILURE);
}
printf("install sig_quit\n");
// Block SIGQUIT and save current signal mask.
sigemptyset(&newmask);
sigaddset(&newmask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
{
perror("signal");
exit(EXIT_FAILURE);
}
printf("Block SIGQUIT,wait 15 seconds\n");
sleep(15); /* SIGQUIT here will remain pending */
if (sigpending(&pendmask) < 0)
{
perror("signal");
exit(EXIT_FAILURE);
}
if (sigismember(&pendmask, SIGQUIT))
printf("\nSIGQUIT pending\n");
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
{
perror("signal");
exit(EXIT_FAILURE);
}
printf("SIGQUIT unblocked\n");
sleep(15); /* SIGQUIT here will terminate with core file */
return 0;
}
static void sig_quit(int signo)
{
printf("caught SIGQUIT,the process will quit\n");
if (signal(SIGQUIT, SIG_DFL) == SIG_ERR)
{
perror("signal");
exit(EXIT_FAILURE);
}
}
运行结果:
终端1:
$ ./sigmask_example &
[3] 3303
install sig_quit
Block SIGQUIT,wait 15 seconds
终端2:
$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
$ kill -SIGQUIT 3303
终端1:
SIGQUIT pending
caught SIGQUIT,the process will quit
SIGQUIT unblocked
3. 进程在捕捉某信号过程中屏蔽的信号
示例代码:
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
int output(sigset_t set)
{
printf("set.val[0]=%x\n",set.__val[0]);
}
void handler(int sig)
{
int i;
sigset_t sysset;
printf("\nin handler sig=%d\n",sig);
sigprocmask(SIG_SETMASK,NULL,&sysset);
output(sysset); //in handler to see the process mask set
printf("return\n");
}
int main(int argc,char *argv[])
{
struct sigaction act;
sigset_t set,sysset,newset;
sigemptyset(&set);
sigemptyset(&newset);
sigaddset(&set,SIGUSR1);
sigaddset(&newset,SIGUSR2);
printf("\nadd SIGUSR1,the value of set:");
output(set);
printf("\nadd SIGUSR2,the value of newset:");
output(newset);
printf("\nafter set proc block set ,and then read to sysset\n");
sigprocmask(SIG_SETMASK,&set,NULL);
sigprocmask(SIG_SETMASK,NULL,&sysset);
printf("system mask is:\n");
output(sysset);
printf("install SIGALRM,and the act.sa_mask is newset(SIGUSR2)\n");
act.sa_handler=handler;
act.sa_flags=0;
act.sa_mask=newset;
sigaction(SIGALRM,&act,NULL);
pause();
printf("after exec ISR\n");
sigemptyset(&sysset);
sigprocmask(SIG_SETMASK,NULL,&sysset);
output(sysset);
}
运行结果:
终端1:
$ ./sigaction_sigset &
[3] 3316
add SIGUSR1,the value of set:set.val[0]=200
add SIGUSR2,the value of newset:set.val[0]=800
after set proc block set ,and then read to sysset
system mask is:
set.val[0]=200
install SIGALRM,and the act.sa_mask is newset(SIGUSR2)
终端2:
$ kill -SIGALRM 3316
终端1:
in handler sig=14
set.val[0]=2a00
return
after exec ISR
set.val[0]=200
原文链接:http://blog.csdn.net/geng823/article/details/40919945