【原创】《Linux高级程序设计》杨宗德著 - 进程管理与程序开发 - 信号集与屏蔽信号 分类: Linux --- 应用程序设计 2014-11-08 13:19 53人阅读 评论(0) 收藏
【原创】《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
版权声明:本文为博主原创文章,未经博主允许不得转载。