手册:
       #include <signal.h>

int sigsuspend(const sigset_t *sigmask);

The   sigsuspend()   function   shall replace the current signal mask of the calling thread with the set of signals pointed to by sigmask and then suspend the thread until delivery of a   signal   whose   action   is either to execute a signal-catching function or to terminate the process. This shall not cause any other signals that may have been pending on the process to become pending on the thread.

If the action is to terminate the process then sigsuspend() shall never return. If the action is to execute   a   signal-catching   function,   then   sigsuspend()   shall return after the signal-catching function returns, with the signal mask restored to the set that existed prior to the sigsuspend() call.

It is not possible to block signals that cannot be ignored. This is enforced by the system without causing an error to be indicated.

也就是说,sigsuspend后,进程就挂在那里,等待着开放的信号的唤醒。系统在接受到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。

Unix提供了等待信号的系统调用,sigsuspend就是其中一个,下面我摘录的解释不错

CU 网友讨论的问题的核心就是到底sigsuspend先返回还是signal handler先返回。这个问题Stevens在《Unix环境高级编程》一书中是如是回答的“If a signal is caught and if the signal handler returns, then sigsuspend returns and the signal mask of the process is set to its value before the call to sigsuspend.”,由于sigsuspend是原子操作,所以这句给人的感觉就是先调用signal handler先返回,然后sigsuspend再返回。但其第一个例子这么讲又说不通,看下面的代码:
CU上讨论该问题起于中的该例子:

int main(void) {
   sigset_t   newmask, oldmask, zeromask;
   if (signal(SIGINT, sig_int) == SIG_ERR)
       err_sys("signal(SIGINT) error");
   sigemptyset(&zeromask);
   sigemptyset(&newmask);
   sigaddset(&newmask, SIGINT);
   /* block SIGINT and save current signal mask */
   if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
       err_sys("SIG_BLOCK error");
   /* critical region of code */
   pr_mask("in critical region: ");
   /* allow all signals and pause */
   if (sigsuspend(&zeromask) != -1)
       err_sys("sigsuspend error");
   pr_mask("after return from sigsuspend: ");
   /* reset signal mask which unblocks SIGINT */
   if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
       err_sys("SIG_SETMASK error");
   /* and continue processing ... */
   exit(0);
}
static void sig_int(int signo) {
   pr_mask("/nin sig_int: ");
   return;
}

结果:
$a.out
in critical region: SIGINT
^C
in sig_int: SIGINT
after return from sigsuspend: SIGINT
如果按照sig_handler先返回,那么SIGINT是不该被打印出来的,因为那时屏蔽字还没有恢复,所有信号都是不阻塞的。那么是Stevens说错了么?当然没有,只是Stevens没有说请在sigsuspend的原子操作中到底做了什么?
sigsuspend的整个原子操作过程为:
(1) 设置新的mask阻塞当前进程;
(2) 收到信号,调用该进程设置的信号处理函数;
(3) 待信号处理函数返回后,恢复原先mask;
(4) sigsuspend返回。

大 致就是上面这个过程,噢,原来signal handler是原子操作的一部分,所以上面的例子是没有问题的,Stevens说的也没错。由于Linux和Unix的千 丝万缕的联系,所以在两个平台上绝大部分的系统调用的语义是一致的。上面的sigsuspend的原子操作也是从《深入理解Linux内核》一书中揣度出 来的。书中的描述如下:
The sigsuspend( ) system call puts the process in the TASK_INTERRUPTIBLE state, after having signaspecifie blocked the standard sid by a bit mask array to which the mask parameter points. The process will wake up only when a nonignored, nonblocked signal is sent to it. The corresponding sys_sigsuspend( ) service routine executes these statements:
mask &= ~(sigmask(SIGKILL) | sigmask(SIGSTOP));
spin_lock_irq(¤t->sigmask_lock);
saveset = current->blocked;
siginitset(¤t->blocked, mask);
recalc_sigpending(current);
spin_unlock_irq(¤t->sigmask_lock);
regs->eax = -EINTR;
while (1) {
     current->state = TASK_INTERRUPTIBLE;
     schedule( );
     if (do_signal(regs, &saveset))
         return -EINTR;
}
而最后的do_signal函数调用则是负责调用User Signal Handler的家伙。我想到这CU上的那个问题该被解疑清楚了吧。

-----------------------------------补充:
清晰且可靠的等待信号到达的方法是先阻塞该信号(防止临界区重入),然后使用 sigsuspend 放开此信号并等待句柄设置信号到达标志。

转自

http://hi.baidu.com/wangjianzhong1981/blog/item/dafaf609c27bf7c73ac76377.html

sigsuspend 函数 释疑相关推荐

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

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

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

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

  3. sigprocmask , sigpending 和 sigsuspend函数

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

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

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

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

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

  6. sigsuspend()函数 解释

    sigsuspend函数作用 :如果在等待信号发生时希望去休眠,则使用sigsuspend函数是非常合适的 头文件:#include <signal.h> 一个保护临界区代码的错误实例:( ...

  7. 10.16 sigsuspend函数

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

  8. sigsuspend()函数解决时序竞态问题

    sigsuspend解决时序竞态问题 使用pause()函数, 会导致在恢复信号集之前程序挂起 #include <unistd.h> #include <signal.h> ...

  9. sigsuspend 函数和 abort 函数

    pause 函数可以阻塞进程以等待一个信号的发生,但如果该信号是阻塞的,那么该信号的传递就会被推迟直到解除阻塞.对应用程序而言,就好像该信号发生在解除阻塞和 pause 之间(取决于内核如何实现信号) ...

最新文章

  1. Spring 是如何解决并发访问的线程安全性问题的
  2. hadoop 1.x升级至hadoop-2.2.0记录
  3. 学计算机的八字,计算机教室八字格言
  4. Druid 数据源连接池配置
  5. 开源 免费 java CMS - FreeCMS1.3-数据对象-mail
  6. C# 动态创建控件时注册Name属性
  7. 华为鸿蒙osbeta在哪看发布会,重磅消息!华为在发布鸿蒙OS2.0手机beta版本后,又发布搭载鸿蒙的新品!!...
  8. jquery checkbox 实现单选
  9. java jframe添加面板_JFrame添加组件的两种方式
  10. Metropolis Hastings MCMC when the proposal and target have differing support
  11. codevs 1164 统计数字
  12. 如何使用终端下载 macOS Monterey 12.1 正式版
  13. Linux_ubuntu16.04 无线/Wifi 上网速度慢的解决方法
  14. python大漠插件官网视频教程_python调用大漠插件教程01注册大漠
  15. wxwidgets自定义事件+调试
  16. win2008服务器c盘在线扩容,win7 win10 win2008系统给主分区C盘增加空间 不破坏原硬盘内容扩充C盘 MiniTool Partition Wizard...
  17. 国内技术管理人员批阅google的“春运交通图”项目
  18. Excel 下拉多选的设置
  19. Elang 学习笔记(二)
  20. lammps计算聚合物例子_MD原理与Lammps实例.ppt

热门文章

  1. JS如何实现多线程?
  2. D. Cloud of Hashtags(逆向贪心)
  3. 学习MySQL的第一步:安装MySQL及数据库可视化工具Navicat
  4. 解码人类基因组:人类基因组计划后17年,X染色体被解码了
  5. Java中间件之介绍
  6. HTML元素脱离文档流的三种方法
  7. 1. HTML学习笔记-2021年11月2日
  8. 桌面、平板、手机和机器人操作系统(ROS)市场占有率数据和趋势分享(附引用2019版)
  9. ASPICE SWE3之——C代码生成软件详细设计1 Doxygen配置
  10. 自动解锁Bitlocker加密硬盘