1、有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数。这种情况是通过阻塞信号实现的。

2、信号阻塞和忽略信号的区别。

阻塞的概念和忽略信号是不同的。操作系统在信号被进程解除阻塞之前不会讲信号传递出去,被阻塞的信号也不会影响进程的行为,信号只是暂时被阻止传递。当进程忽略一个信号时,信号会被传递出去但进程会将信号丢弃。

3、信号阻塞系统调用,它们的都起到阻塞的作用,它们不是协作使用的。

  1. #include <signal.h>
  2. int sigprocmask(ubt how,const sigset_t*set,sigset_t *oldset);
  3. 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。

sigprocmask示例(演示添加信号掩码):

 #include <stdio.h>
#include <signal.h>
void checkset(); void main()
{
sigset_tblockset;
sigemptyset(&blockset);
sigaddset(&blockset,SIGINT);
sigaddset(&blockset,SIGTSTP); &nbsp;checkset(); sigprocmask(SIG_SETMASK,&blockset,NULL);
checkset(); &nbsp; sigaddset(&blockset,SIGTERM);
sigprocmask(SIG_BLOCK,&blockset,NULL);
checkset(); sigdelset(&blockset,SIGTERM);
sigprocmask(SIG_UNBLOCK,&blockset,NULL);
checkset();
} void checkset()
{ sigset_tset set;
printf("checksetstart:\n"); if(sigprocmask(,NULL,&set)<)
{
printf("checksetsigprocmask error!!\n");
exit();
} if(sigismember(&set,SIGINT))
printf("sigint\n");
if(sigismember(&set,SIGTSTP))
printf("sigtstp\n"); if(sigismember(&set,SIGTERM))
printf("sigterm\n");
printf("checksetend\n");
}

sigprocmask示例(演示添某部分代码不被信号打搅):

 #include <stdio.h>
#include <signal.h>
void checkset(); void func();
void main()
{
sigset_tblockset,oldblockset,pendmask;
printf("pid:%ld\n",(long)getpid()); signal(SIGINT,func); //信号量捕捉函数,捕捉到SIGINT,跳转到函数指针func处执行 sigemptyset(&blockset); //初始化信号量集
sigaddset(&blockset,SIGTSTP); //将SIGTSTP添加到信号量集中
&nbsp;sigaddset(&blockset,SIGINT);//将SIGINT添加到信号量集中 sigprocmask(SIG_SETMASK,&blockset,&oldblockset); //将blockset中的SIGINT,SIGTSTP阻塞掉,并保存当前信号屏蔽字 /*执行以下程序时,不会被信号打搅*/
checkset();
&nbsp;sleep();
sigpending(&pendmask); //检查信号是悬而未决的
if(sigismember(&pendmask,SIGINT)) //SIGINT是悬而未决的。所谓悬而未决,是指SIGQUIT被阻塞还没有被处理
printf("SIGINTpending\n"); /*免打搅结束*/ sigprocmask(SIG_SETMASK,&oldblockset,NULL); //恢复被屏蔽的信号SIGINT SIGTSTP
printf("SIGINTunblocked\n");
sleep();
} void checkset()
{
sigset_tset;
printf("checksetstart:\n");
if(sigprocmask(,NULL,&set)<)
{
printf("checksetsigprocmask error!!\n");
exit();
}
if(sigismember(&set,SIGINT))
printf("sigint\n"); if(sigismember(&set,SIGTSTP))
printf("sigtstp\n"); if(sigismember(&set,SIGTERM))
printf("sigterm\n"); &nbsp; printf("checksetend\n"); }
void func()
{
printf("hellofunc\n");
}

sigeprocmask函数通常和sigemptyset、sigfillset、sigaddset、sigdelset、 sigismember函数配合使用,主要有两种用途:

1.我们不希望某些不太重要的信号来影响我们的进程,我们就可以把这些信号添加到信号屏蔽集中。使它们不打扰进程的执行。

2.如果系统现在很忙,没有时间及时相应信号,进程可以先把信号阻塞掉,等系统有空闲时间在去相应,这也保证了信号的可靠性。

例二:

 #include<stdio.h>
#include<stdlib.h>
#include<signal.h> sigset_t newmask,oldmask,pendmask; void sig_usr(int signo)
{
printf("this is sig_usr!\n"); } int main(int argc, char *argv[])
{ if(signal(SIGUSR1,sig_usr) == SIG_ERR){
printf("signal error!\n");
exit();
} sigemptyset(&newmask);
sigaddset(&newmask,SIGUSR1);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < ){
printf("sig_block error!\n");
exit();
} printf("first raise(SIGUSR1)!\n");
raise(SIGUSR1);
if(sigpending(&pendmask) < ){
printf("sigpending error!\n");
exit();
} if(sigismember(&pendmask, SIGUSR1))
printf("sigusr1 pending!\n"); if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < ){
printf("sig_setmask error!\n");
exit();
} printf("second raise(SIGUSR1)!\n");
raise(SIGUSR1); printf("main end!\n");
exit();
}

结果如下:

如果注释掉下面的代码

      if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < ){
printf("sig_setmask error!\n");
exit();
}

结果如下:

发现第一次发送的信号也不会处理了。笔者也不知道为什么会发生这种情况,还是下次写代码的时候注意一下,阻塞完信号,处理的时候要及时恢复好了!

若只注释掉下面的代码:

      if(sigpending(&pendmask) < ){
printf("sigpending error!\n");
exit();
} if(sigismember(&pendmask, SIGUSR1))
printf("sigusr1 pending!\n");

而留下:

       if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < ){
printf("sig_setmask error!\n");
exit();
}

结果第一次发送的信号也会有响应,截图如下:

看来在阻塞信号的时候接收到了信号,当恢复信号屏蔽字的时候信号也会得到处理!

【C】——sigprocmask 阻塞进程信号的更多相关文章

  1. sigprocmask阻塞信号

    有时候不希望在接到信号时就立即停止当前执行,去处理信号,同时也不希望忽略该信号,而是延时一段时间去调用信号处理函数 1. 信号阻塞和忽略信号的区别 操作系统在信号被进程解除阻塞之前不会将信号传递出去, ...

  2. Linux 信号详解五(信号阻塞,信号未决)

    信号在内核中的表示 执行信号的处理动作成为信号递达(Delivery),信号从产生到递达之间的状态称为信号未决(Pending).进程可以选择阻塞(Block)某个信号. 被阻塞的信号产生时将保持在未 ...

  3. [Linux]返回被阻塞的信号集

    一.概述 在另一篇实例说到,进程可以屏蔽它不想接收的信号集. 事实上这些被屏蔽的信号只是阻塞在内核的进程表中,因为他们不能递送给进程,所以状态是未决的(pending). 利用sigpending函数 ...

  4. UNIX环境编程学习笔记(24)——信号处理进阶学习之信号集和进程信号屏蔽字

    lienhua342014-11-03 1 信号传递过程 信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程.从信号产生到传递给目标进程的流程图如图 1 所示, 图 1: 信 ...

  5. APUE学习笔记5——信号、信号集和进程信号屏蔽字

    1 信号传递过程 当引发信号的事件发生时(如软硬件异常.软件定时.终端产生信号或调用kill函数等等),会产生信号,内核会发送给目标进程. 在信号产生到信号传递给目标进程之间的时间间隔内,称该信号为未 ...

  6. 进程信号的未决状态(pending status)

    这两天看了apue有关进程信号的部分,觉得未决状态这个词很是不一般,呵呵.一开始当我看到这个词,我不理解,什么意思呢,读了好几遍.不知道是书里面讲的晦涩难懂,还是脑子越来越不行了,就是没有搞明白.后来 ...

  7. 进程&信号&管道实践学习记录

    程序分析 exec1.c & exect2.c & exect3.c 程序代码 (以exect1.c为例,其他两个结构类似) #include <stdio.h> #inc ...

  8. PHP 中的多进程使用,进程通信、进程信号等详解

    多进程环境要求 Linux 系统 php-cli 模式 pcntl 扩展 或 swoole 扩展 pcntl 扩展 <?php $str = "hello world!" . ...

  9. SqlServer中——查找杀死阻塞进程

    查找阻塞进程: SELECT blocking_session_id '阻塞进程的ID', wait_duration_ms '等待时间(毫秒)', session_id '(会话ID)' FROM ...

随机推荐

  1. jQueryUI modal dialog does not show close button (x) JQueryUI和BootStrap混用时候,右上角关闭按钮显示不出图标的解决办法

    I had this problem and was able to resolve it with the declaration below. $.fn.bootstrapBtn = $.fn.b ...

  2. Universal USB Installer集开源软件之佳作

    有机会下载一份uui的源代码,翻看了一下,呵呵,有意思,几乎是一个开源软件的大杂烩,忽然,恍然大悟,原来,作者才是开源软件精神的代言人,不重复制造轮子的践行者啊. uui网址:https://www. ...

  3. PHP将CMYK颜色值和RGB颜色相互转换的例子

    PHP将CMYK颜色值和RGB颜色相互转换的例子 function hex2rgb($hex) { $color = str_replace('#','',$hex); $rgb = array('r ...

  4. 【Unity】第5章 3D坐标系和天空盒

    分类:Unity.C#.VS2015 创建日期:2016-04-20 一.简介 这一张主要介绍3D坐标系的基础知识以及各种形状的天空盒. 二.示例 本章的示例都在ch05Demos工程下.

  5. Redis为什么使用单进程单线程方式

    Redis采用的是基于内存的采用的是单进程单线程模型的KV数据库,由C语言编写.官方提供的数据是可以达到100000+的qps.这个数据不比采用单进程多线程的同样基于内存的KV数据库Memcached ...

  6. JAVA与C++,C与C++的差别

    首先来分析JAVA与C++的差别: JAVA是纯面向对象的语言,而C++是基于面向对象过程的语言. JAVA有着垃圾回收机制.它的语法是C++的子集,即JAVA有的C++都有.而C++有的JAVA不全 ...

  7. 菜鸟学SSH(七)——Spring jar包详解

    Struts.Hibernate.Spring这类的框架给我们开发带来非常大的好处,让我们更加快速.有效的开发.所以我们在开发中通常都会用到各种框架,每个框架都有很多jar包,每个jar都有各自不同的 ...

  8. android笔记---LoginActivity extends FinalActivity

    package com.fuda.activity; import java.io.BufferedReader; import java.io.File; import java.io.FileNo ...

  9. angular学习笔记(三十)-指令(1)-概述

    之前在 angular学习笔记(十九)-指令修改dom 里面已经简单的提到了angular中的指令,现在来详细的介绍 '指令' 一.指令的创建: dirAppModule.directive('dir ...

  10. Up and running with Apache Spark on Apache Kudu

    After the GA of Apache Kudu in Cloudera CDH 5.10, we take a look at the Apache Spark on Kudu integra ...