sigsuspend函数作用 :如果在等待信号发生时希望去休眠,则使用sigsuspend函数是非常合适的

头文件:#include <signal.h>

一个保护临界区代码的错误实例:(sigprocmask()和pause()实现)

#include <unistd.h>
#include <signal.h>
#include <stdio.h>void handler(int sig)    //信号处理函数的实现
{printf("SIGINT sig");
}
int main()
{sigset_t new,old;struct sigaction act;act.sa_handler = handler;  //信号处理函数handlersigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGINT, &act, 0);  //准备捕捉SIGINT信号sigemptyset(&new);sigaddset(&new, SIGINT);sigprocmask(SIG_BLOCK, &new, &old);  //将SIGINT信号阻塞,同时保存当前信号集printf("Blocked");sigprocmask(SIG_SETMASK, &old, NULL);  //取消阻塞pause();return 0;
}

上面实例的问题是:本来期望pause()之后,来SIGINT信号,可以结束程序;可是,如果当“取消阻塞”和“pause”之间,正好来了SIGINT信号,结果程序因为pause的原因会一直挂起。。。

如果在信号阻塞时将其发送给进程,那么该信号的传递就被推迟直到对它解除了阻塞。对应用程序而言,该信号好像发生在解除对SIGINT的阻塞和pause之间。如果发生了这种情况,或者如果在解除阻塞时刻和pause之间确实发生了信号,那么就产生了问题。因为我们可能不会再见到该信号,所以从这种意义上而言,在此时间窗口(解除阻塞和pause之间)中发生的信号丢失了,这样就使pause永远阻塞。

为了纠正此问题,需要在一个原子操作中先恢复信号屏蔽字,然后使进程休眠。这种功能是由sigsuspend函数提供的。

#include <signal.h>int sigsuspend( const sigset_t *sigmask );
返回值:-1,并将errno设置为EINTR

将进程的信号屏蔽字设置为由sigmask指向的值。在捕捉到一个信号或发生了一个会终止该进程的信号之前,该进程被挂起。如果捕捉到一个信号而且从该信号处理程序返回,则sigsuspend返回,并且将该进程的信号屏蔽字设置为调用sigsuspend之前的值。

注意,此函数没有成功返回值。如果它返回到调用者,则总是返回-1,并将errno设置为EINTR(表示一个被中断的系统调用)。

3)使用sigsuspend()的程序

#include <unistd.h>
#include <signal.h>
#include <stdio.h>
void handler(int sig)   //信号处理程序
{if(sig == SIGINT)printf("SIGINT sig");else if(sig == SIGQUIT)printf("SIGQUIT sig");elseprintf("SIGUSR1 sig");
}int main()
{sigset_t new,old,wait;   //三个信号集struct sigaction act;act.sa_handler = handler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGINT, &act, 0);    //可以捕捉以下三个信号:SIGINT/SIGQUIT/SIGUSR1sigaction(SIGQUIT, &act, 0);sigaction(SIGUSR1, &act, 0);sigemptyset(&new);sigaddset(&new, SIGINT);  //SIGINT信号加入到new信号集中sigemptyset(&wait);sigaddset(&wait, SIGUSR1);  //SIGUSR1信号加入waitsigprocmask(SIG_BLOCK, &new, &old);       //将SIGINT阻塞,保存当前信号集到old中//临界区代码执行    if(sigsuspend(&wait) != -1)  //程序在此处挂起;用wait信号集替换new信号集。即:过来SIGUSR1信  号,阻塞掉,程序继续挂起;过来其他信号,例如SIGINT,则会唤醒程序。执行sigsuspend的原子操作。注意:如果“sigaddset(&wait, SIGUSR1);”这句没有,则此处不会阻塞任何信号,即过来任何信号均会唤醒程序。printf("sigsuspend error");printf("After sigsuspend");sigprocmask(SIG_SETMASK, &old, NULL);return 0;
}

sigsuspend的原子操作是:
(1)设置新的mask阻塞当前进程(上面是用wait替换new,即阻塞SIGUSR1信号)
(2)收到SIGUSR1信号,阻塞,程序继续挂起;收到其他信号,恢复原先的mask(即包含SIGINT信号的)。
(3)调用该进程设置的信号处理函数(程序中如果先来SIGUSR1信号,然后过来SIGINT信号,则信号处理函数会调用两次,打印不同的内容。第一次打印SIGINT,第二次打印SIGUSR1,因为SIGUSR1是前面阻塞的)

(4)待信号处理函数返回,sigsuspend返回了。(sigsuspend将捕捉信号和信号处理函数集成到一起了)

注:sigsuspend实际是将sigprocmask和pause结合起来原子操作。

转自:http://blog.sina.com.cn/s/blog_6af9566301013xp4.html 和http://www.cnblogs.com/nufangrensheng/category/543313.html

sigsuspend()函数 解释相关推荐

  1. Linux信号实现精确到微秒的sleep函数:通过sigsuspend函数解决时序竞态问题

    原理就是先使用定时器定时,然后再使用pause函数或者sigsuspend函数主动阻塞挂起,最终恢复现场. 如果使用pause函数的话,优点是使用简单,缺点是有可能产生时序竞态,导致进程一直阻塞下去: ...

  2. sigsuspend函数(mysleep函数的改进)

    可以通过设置屏蔽SIGALRM的方法来控制程序执行逻辑,但无论如何设置,程序都有可能在"解除信号屏蔽"与"挂起等待信号"这个两个操作间隙失去cpu资源.除非将这 ...

  3. 回旋矩形C语言,C语言回旋函数解释下,该如何处理

    当前位置:我的异常网» C语言 » C语言回旋函数解释下,该如何处理 C语言回旋函数解释下,该如何处理 www.myexceptions.net  网友分享于:2013-06-08  浏览:30次 C ...

  4. sigprocmask , sigpending 和 sigsuspend函数

    sigprocmask函数: 功能描述: 设定对信号屏蔽集内的信号的处理方式(阻塞或不阻塞). 用法: #include <signal.h> int sigprocmask(int ho ...

  5. 信号驱动任务执行(pause、sigsuspend函数)

    信号驱动任务指的是通过信号来驱动任务的执行,每发送一次信号,任务就执行一次.实现该目的所需的函数就是 pause 或者 sigsuspend,pause和sigsuspend函数可以暂停当前进程,直至 ...

  6. matlab中bwmorph函数的作用,Matlab中的bwmorph函数解释

    Matlab中的bwmorph函数解释 bwmorph:对二值图像的形态学操作. BW2 = bwmorph(BW,operation) BW2 =bwmorph(BW,operation,n) BW ...

  7. CreateFile函数解释

    CreateFile函数解释 API函数CreateFile可打开和创建文件.管道.邮槽.通信服务.设备以及控制台,但是在此时只是介绍用这个函数怎么实现创建和打开一个文件. HANDLE Create ...

  8. Unix/Linux编程:竞态条件与sigsuspend函数

    利用pause和alarm函数实现sleep #include <unistd.h>int pause(void); pause函数使调用进程挂起直到有信号到达.如果信号的处理动作是终止进 ...

  9. 10.16 sigsuspend函数

    我们已经学习了如何修改进程的信号掩码,实现指定信号的阻塞与接触阻塞.我们可以使用这一技术来保护临界区域的代码(当在这一段区域内执行代码的时候哦,我们不希望被信号中断),但是如果我们想要接触一个信号的阻 ...

最新文章

  1. Caffe官方教程翻译(10):Editing model parameters
  2. The import java.util cannot be resolved
  3. Spring配置文件-Bean实例化的三种方式
  4. python接口自动化测试(二)-requests.get()
  5. js中四种创建对象的方式
  6. LintCode Find the Weak Connected Component in the Directed Graph
  7. mp4v2 写mp4 java_使用mp4v2将H264+AAC合成mp4文件
  8. Github PageHelper 原理解析
  9. CMD执行命令出现NOMALY: meaningless REX prefix used以及IDEA提示Cannot run git问题解决
  10. paip.ASP 开发调试大总结
  11. SQLyog注册激活码
  12. E盾V60原版网络验证包含个人动手改IP地址源码软件加密一机一码
  13. 工作环境的改善---提高工作效率和工作质量
  14. 【Jquery】Jquery操作table表格详细说明
  15. 放眼看政策!2022年武汉市光谷招贤令奖励补贴政策以及申报条件!
  16. 22考研全年备考规划表,这5个时间点你必须知道!
  17. Java将html转换成pdf、html转换成图片
  18. 经典同态加密算法Paillier解读 - 原理、实现和应用
  19. PTA单链表 - 20. 单值化(去重)
  20. docker的容器下使用apt-get update卡在[0%] Working问题解决办法

热门文章

  1. Linux之Ubuntu入门篇
  2. 【数字信号处理】卷积编程实现 ( 卷积计算原理 | 卷积公式计算 | 使用 matlab 计算卷积 | 使用 C 语言实现卷积计算 )
  3. 几种简单卷积计算方法实例-Faltung
  4. ORACLE这门武功
  5. JS中函数式编程详解版(FunctionalProgramming,FP)
  6. 你就像烟火的美丽,那么美丽
  7. Excel中HLOOKUP函数实例(一):自动判断并获取数据
  8. sonarqube更新最新包含阿里p3c的pmd插件
  9. js跳出循环的三种方法
  10. Redis学习笔记之十:Redis用作消息队列