sigemptyset,sigfillset,sigaddset,sigdelset,sigismember,sigprocmask,sigpendmask作用
2015-12-04 16:54
549 查看
SYNOPSIS #include <signal.h> int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signum); int sigdelset(sigset_t *set, int signum); int sigismember(const sigset_t *set, int signum);
以上都是信号集操作函数,如果是glibc,还额外提供了以下3个函数
int sigisemptyset(sigset_t *set); int sigorset(sigset_t *dest, sigset_t *left, sigset_t *right); int sigandset(sigset_t *dest, sigset_t *left, sigset_t *right);
描述:
查看linux3.13 signal.h文件源码,一共有31个用户可用的信号,信号集用每一位对应于一个信号。
sigemptyset
初始化信号集set,将指定的信号集set清空,即set的值为0。
sigfillset
初始化信号集set,将指定的信号集set全部置位,即set值为0x7FFFFFFF
sigaddset
将信号signum对应于信号集set的那一位置位
sigdelset
将信号signum对应于信号集set的那一位清零
以上4个函数成功返回0,否则返回-1
sigismember
查询信号signum是否在信号集中置位了。如果置位了,返回1,否则返回0
glibc的扩展信号集操作函数:
sigisemptyset
信号集set是否清空了
sigorset
获得信号集left,right的并集,存放到dest
sigandset
获得信号集left,right的交集,存放到dest
扩展函数的测试程序:
sigset_t sigdest, sigleft, sigright; sigemptyset(&sigdest); sigemptyset(&sigleft); sigemptyset(&sigright); sigaddset(&sigleft, SIGALRM); sigaddset(&sigleft, SIGINT); sigaddset(&sigright, SIGALRM); sigaddset(&sigright, SIGQUIT); printf("\nSIG union\n"); sigorset(&sigdest, &sigleft, &sigright); if ( sigismember(&sigdest, SIGALRM ) ) { printf("SIGALRM\n"); } if ( sigismember(&sigdest, SIGINT ) ) { printf("SIGINT\n"); } if ( sigismember(&sigdest, SIGQUIT ) ) { printf("SIGQUIT\n"); } printf("\nSIG intersection\n"); sigemptyset(&sigdest); sigandset(&sigdest, &sigleft, &sigright); if ( sigismember(&sigdest, SIGALRM ) ) { printf("SIGALRM\n"); } if ( sigismember(&sigdest, SIGINT ) ) { printf("SIGINT\n"); } if ( sigismember(&sigdest, SIGQUIT ) ) { printf("SIGQUIT\n"); }
运行结果:
SIG union SIGALRM SIGINT SIGQUIT SIG intersection SIGALRM
sigprocmask函数
SYNOPSIS #include <signal.h> int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
根据动作how修改或者获取,或者修改并获取当前调用进程的信号掩码(一个信号集)。how有一下值可选:
SIG_BLOCK
将阻塞信号集设置为当前阻塞信号集oldset和指定的信号集的并集,相当于一个或操作
SIG_UNBLOCK
根据设置的信号集set,将当前阻塞信号集oldset对应的位清除,使其不阻塞。
SIG_SETMASK
将阻塞信号集设置为指定信号集set。
如果oldset不为NULL,则函数返回时,oldset指向的内容为调用函数前进程信号掩码,也就是可以获取函数调用之前的信号掩码。
如果set为NULL,则进程信号掩码不会更改,how将被忽略,如果此时oldset不为空,则可以获得之前的信号掩码。
需要注意的是sigprocmask只对单线程或者单进程有效,多线程中要使用thread_sigmask函数。还有就是SIGSTOP,SIGKILL是不会被阻塞的,即使指定了也会忽略。
进程中的每个线程都有其各自独立的signal mask。
子进程会获得父线程同样的signal mask。
sigpending
SYNOPSIS #include <signal.h> int sigpending(sigset_t *set);
sigpending,获得调用进程挂起的信号集,所谓挂起就是指有信号发往这个进程,但是此时被阻塞了,等阻塞解除,就会送至进程里面。
下面是一个综合的例子(来自APUE):
static void sig_int(int signo) { printf("catch SIGINT\n"); if ( signal(SIGINT, SIG_DFL) == SIG_ERR ) { perror("signal\n"); } } int main ( int argc, char *argv[] ) { sigset_t newset,oldset,pendmask; if ( signal(SIGINT,sig_int) == SIG_ERR ) { perror("signal\n"); } if ( sigemptyset(&newset) < 0 ) { perror("sigempty\n"); } if ( sigaddset(&newset, SIGINT) < 0 ) { perror("sigaddset\n"); } if ( sigprocmask(SIG_BLOCK, &newset, &oldset) < 0 ) { perror("sigprocmask\n"); } printf("\nSIGINT block\n"); sleep(5); if ( sigpending(&pendmask) < 0) { perror("sigpending\n"); } if ( sigismember(&pendmask, SIGINT) ) { printf("SIGINT is pendding\n"); } if ( sigprocmask(SIG_SETMASK, &oldset, NULL) < 0 ) { perror("sigprocmask\n"); } printf("\nSIGINT unblock\n"); sleep(5); return 0; }
在进入第一次睡眠前,设置好了信号掩码,SIGINT将被阻塞,若在唤醒前按下ctrl+c(发送SIGINT),不会进行任何响应,事实上,如果不进行阻塞的话,收到任何信号将会唤醒sleep。等到第二次调用sigprocmask将signal mask恢复,则之前的那个SIGINT就会被响应,再次按下ctrl+c,int立马解除了第二个sleep。
运行结果:
SIGINT block ^C^C <----------此处阻塞了 SIGINT is pendding catch SIGINT SIGINT unblock ^C <------------此处立马响应
并且可以看到,第一次连续发了2个SIGINT但是下面只响应了一次,说明阻塞的信号并不会在一个阻塞队列里面。
相关文章推荐
- 从输入网址到显示网页的全过程分析
- app集成微信支付服务器端开发(java)
- 同一个服务器部署两个Tomcat并用Nginx实现负载分担
- Android之DDMS无法查看data目录, 并查看数据库的方法
- 老猪带你玩转android自定义控件一——打造最简单viewpagerindicator
- iOS中的 .p12 证书的应用
- RxJava教程(一)
- 博客建成第一篇
- 进制转换
- 欢迎使用CSDN-markdown编辑器
- 使用 jquery 事件委托的 on 方法
- linux下extundelete恢复ext4删除的文件
- CSS布局奇淫技巧之--各种居中
- The beginning iOS8 Programming with Swift 中文翻译 - 5
- Extract Fasta Sequences Sub Sets by position
- render 函数小分析
- php 批量插入字段
- 浅谈springSecurity
- MySQL 分区表详解
- Intellij idea处理Spring MVC单元测试问题