信号基本操作之sigprocmask阻塞进程
2017-08-31 17:58
615 查看
1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。
2、信号阻塞和忽略信号的区别。
阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。
3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。
sigprocmask设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。
参数:
how:用于指定信号修改的方式,可能选择有三种
SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。
SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。
SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。
set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。
oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。
返回说明:
成功执行时,返回0。失败返回-1,errno被设为EINVAL。
直接上代码来直观看问题。
这里打印的效果如下所示:
解释如下:
第一步:没有注册信息,因此没有打印
第二步:注册了SIGINT和SIGSTP,因此打印相应的信号量
第三步:添加信号以及sigprocmask(SIG_BLOCK,&blockset,NULL)或操作,因此打印三个。
第四步:删除信号以及sigprocmask(SIG_UNBLOCK,&blockset,NULL)与操作,因此删除其余的两个
下面另外一个demo,如下
打印如下:
这里的步骤如下:
第一步:检测了当前进程的信号量
第二步:进入sleep之后,终端敲入Ctrl+C,但是由于信号屏蔽了,不会中断处理,于是需要等待10S
第三步:sigsupend检查信号是悬而未决的,然后检查SIGINT是否收到,收到,则打印。
第四步:收到SIGINT之后,马上中断程序,进入信号处理程序,打印helofunc
第五步:退到主程序,休眠,然后退出主程序。
2、信号阻塞和忽略信号的区别。
阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。
3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。
、#include <signal.h> int sigprocmask(ubt how,const sigset_t*set,sigset_t *oldset); int sigsuspend(const sigset_t*sigmask);
sigprocmask设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞)。
参数:
how:用于指定信号修改的方式,可能选择有三种
SIG_BLOCK//将set所指向的信号集中包含的信号加到当前的信号掩码中。即信号掩码和set信号集进行或操作。
SIG_UNBLOCK//将set所指向的信号集中包含的信号从当前的信号掩码中删除。即信号掩码和set进行与操作。
SIG_SETMASK //将set的值设定为新的进程信号掩码。即set对信号掩码进行了赋值操作。
set:为指向信号集的指针,在此专指新设的信号集,如果仅想读取现在的屏蔽值,可将其置为NULL。
oldset:也是指向信号集的指针,在此存放原来的信号集。可用来检测信号掩码中存在什么信号。
返回说明:
成功执行时,返回0。失败返回-1,errno被设为EINVAL。
直接上代码来直观看问题。
#include <stdio.h> #include <signal.h> void checkset(); void main() { sigset_t blockset; sigemptyset(&blockset); sigaddset(&blockset,SIGINT); sigaddset(&blockset,SIGTSTP); printf("=====111111111111111==============\n"); checkset(); sigprocmask(SIG_SETMASK,&blockset,NULL); printf("=====222222222222222222==============\n"); checkset(); sigaddset(&blockset,SIGTERM); sigprocmask(SIG_BLOCK,&blockset,NULL); printf("========3333333333333333333==============\n"); checkset(); sigdelset(&blockset,SIGTERM); sigprocmask(SIG_UNBLOCK,&blockset,NULL); printf("========4444444444444444444==============\n"); checkset(); } void checkset() { sigset_t set; printf("check set start:\n"); if(sigprocmask(0,NULL,&set)<0) { printf("check setsigprocmask error!!\n"); exit(0); } if(sigismember(&set,SIGINT)) printf("sig SIGINT\n"); if(sigismember(&set,SIGTSTP)) printf("sig SIGTSTP\n"); if(sigismember(&set,SIGTERM)) printf("sig SIGTERM\n"); printf("check set end\n"); }
这里打印的效果如下所示:
解释如下:
第一步:没有注册信息,因此没有打印
第二步:注册了SIGINT和SIGSTP,因此打印相应的信号量
第三步:添加信号以及sigprocmask(SIG_BLOCK,&blockset,NULL)或操作,因此打印三个。
第四步:删除信号以及sigprocmask(SIG_UNBLOCK,&blockset,NULL)与操作,因此删除其余的两个
下面另外一个demo,如下
#include <stdio.h> #include <signal.h> void checkset(); void func(); void main() { sigset_t blockset,oldblockset,pendmask; printf("pid:%ld\n",(long)getpid()); signal(SIGINT,func); //信号量捕捉函数,捕捉到SIGINT,跳转到函数指针func处执行 sigemptyset(&blockset); //初始化信号量集 sigaddset(&blockset,SIGTSTP); //将SIGTSTP添加到信号量集中 sigaddset(&blockset,SIGINT);//将SIGINT添加到信号量集中 sigaddset(&blockset,SIGTERM);//将SIGTERM添加到信号量集中 sigaddset(&blockset,SIGRTMIN+12);//将SIGRTMIN+12添加到信号量集中 sigaddset(&blockset,SIGRTMIN+13);//将SIGRTMIN+13添加到信号量集 sigprocmask(SIG_SETMASK,&blockset,&oldblockset); //将blockset中的SIGINT,SIGTSTP阻塞掉,并保存当前信号屏蔽字 /*执行以下程序时,不会被信号打搅*/ checkset(); sleep(10); sigpending(&pendmask); //检查信号是悬而未决的 if(sigismember(&pendmask,SIGINT)) //SIGINT是悬而未决的。所谓悬而未决,是指SIGINT被阻塞还没有被处理 printf("SIGINT pending\n"); /*免打搅结束*/ sigprocmask(SIG_SETMASK,&oldblockset,NULL); //恢复被屏蔽的信号SIGINT SIGTSTP SIGTERM SIGRTMIN+12 SIGRTMIN+13 printf("SIGINT unblocked\n"); sleep(10); } void checkset() { sigset_t set; printf("checkset start:\n"); if(sigprocmask(0,NULL,&set)<0) { printf("check setsigprocmask error!!\n"); exit(0); } if(sigismember(&set,SIGINT)) printf("sigint\n"); if(sigismember(&set,SIGTSTP)) printf("sigtstp\n"); if(sigismember(&set,SIGTERM)) printf("sigterm\n"); if(sigismember(&set,SIGILL)) printf("SIGILL\n"); if(sigismember(&set,SIGRTMIN+12)) printf("SIGRTMIN+12\n"); if(sigismember(&set,SIGRTMIN+13)) printf("SIGRTMIN+12\n"); printf("checkset end\n"); } void func() { printf("hellofunc\n"); }
打印如下:
这里的步骤如下:
第一步:检测了当前进程的信号量
第二步:进入sleep之后,终端敲入Ctrl+C,但是由于信号屏蔽了,不会中断处理,于是需要等待10S
第三步:sigsupend检查信号是悬而未决的,然后检查SIGINT是否收到,收到,则打印。
第四步:收到SIGINT之后,马上中断程序,进入信号处理程序,打印helofunc
第五步:退到主程序,休眠,然后退出主程序。
相关文章推荐
- 【C】——sigprocmask 阻塞进程信号
- sigprocmask 阻塞进程
- sigprocmask和信号阻塞
- sigemptyset、sigaddset、sigprocmask的用法 信号未决,信号阻塞 信号的捕捉
- 2信号处理之:信号产生原因,进程处理信号行为,信号集处理函数,PCB的信号集,sigprocmask()和sigpending(),信号捕捉设定,sigaction,C标准库信号处理函数,可重入函数,
- sigprocmask 阻塞进程
- 那年,一步一步学linux c ---sigprocmask 阻塞进程
- 那年,一步一步学linux c ---sigprocmask 阻塞进程
- sigprocmask阻塞信号
- sigprocmask阻塞信号
- 等待单个进程信号的正确方法 sigprocmask
- sigprocmask 阻塞进程
- sigprocmask 阻塞进程
- 进程的信号掩码【sigprocmask(int what,const sigset_t *set,sigset_t *oldset)】
- 那年,一步一步学linux c ---sigprocmask 阻塞进程---sem_wait/sem_post
- Linux信号控制-sigprocmask,sigsuspend,sigpending,sigaction,sigqueue
- Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()
- Linux c之 信号屏蔽字sigprocmask()
- Unix环境高级编程(阅读笔记)----信号集、信号屏蔽函数sigprocmask
- APUE 程序清单10-11 信号设置和sigprocmask实例