函数原型:

  #include <signal.h>   int sigsuspend(const sigset_t *mask);

作用:

  用于在接收到某个信号之前,临时用mask替换进程的信号掩码,并暂停进程执行,直到收到信号为止。   The sigsuspend() function replaces the current signal mask of the calling thread with the set of signals pointed to by sigmask and then suspends the thread until delivery of a signal whose action is either to execute a signal-catching function or to terminate the process. This will 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() will never return. If the action is to execute a signal-catching function, thensigsuspend() will return after the signal-catching function returns, with the signal mask restored to the set that existed prior to thesigsuspend() 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后,进程就挂在那里,等待着开放的信号的唤醒。系统在接收到信号后,马上就把现在的信号集还原为原来的,然后调用处理函数。


返回值:

  sigsuspend返回后将恢复调用之前的的信号掩码。信号处理函数完成后,进程将继续执行。该系统调用始终返回-1,并将errno设置为EINTR.   Since sigsuspend() suspends process execution indefinitely, there is no successful completion return value. If a return occurs, -1 is returned and errno is set to indicate the error.   The sigsuspend() function will fail if:   [EINTR]   A signal is caught by the calling process and control is returned from the signal-catching function.


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


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再返回。

[cpp] view plaincopyprint?
  1. int main(void) {
  2. sigset_t   newmask, oldmask, zeromask;
  3. if (signal(SIGINT, sig_int) == SIG_ERR)
  4. err_sys("signal(SIGINT) error");
  5. sigemptyset(&zeromask);
  6. sigemptyset(&newmask);
  7. sigaddset(&newmask, SIGINT);
  8. /* block SIGINT and save current signal mask */
  9. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
  10. err_sys("SIG_BLOCK error");
  11. /* critical region of code */
  12. pr_mask("in critical region: ");
  13. /* allow all signals and pause */
  14. if (sigsuspend(&zeromask) != -1)
  15. err_sys("sigsuspend error");
  16. pr_mask("after return from sigsuspend: ");
  17. /* reset signal mask which unblocks SIGINT */
  18. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  19. err_sys("SIG_SETMASK error");
  20. /* and continue processing ... */
  21. exit(0);
  22. }
  23. static void sig_int(int signo) {
  24. pr_mask("\nin sig_int: ");
  25. return;
  26. }

结果:

[cpp] view plaincopyprint?
  1. $a.out
  2. in critical region: SIGINT
  3. ^C
  4. in sig_int: SIGINT
  5. after return from sigsuspend: SIGINT

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


[cpp] view plaincopyprint?
  1. #include <stdio.h>
  2. #include <signal.h>
  3. void checkset();
  4. void func();
  5. void main()
  6. {
  7. sigset_tblockset,oldblockset,zeroset,pendmask;
  8. printf("pid:%ld\n",(long)getpid());
  9. signal(SIGINT,func);
  10. sigemptyset(&blockset);
  11. sigemptyset(&zeroset);
  12. sigaddset(&blockset,SIGINT);
  13. sigprocmask(SIG_SETMASK,&blockset,&oldblockset);
  14. checkset();
  15. sigpending(&pendmask);
  16. if(sigismember(&pendmask,SIGINT))
  17. printf("SIGINTpending\n");
  18. if(sigsuspend(&zeroset)!= -1)
  19. {
  20. printf("sigsuspenderror\n");
  21. exit(0);
  22. }
  23. printf("afterreturn\n");
  24. sigprocmask(SIG_SETMASK,&oldblockset,NULL);
  25. printf("SIGINTunblocked\n");
  26. }
  27. void checkset()
  28. {    sigset_tset;
  29. printf("checksetstart:\n");
  30. if(sigprocmask(0,NULL,&set)<0)
  31. {
  32. printf("checksetsigprocmask error!!\n");
  33. exit(0);
  34. }
  35. if(sigismember(&set,SIGINT))
  36. printf("sigint\n");
  37. if(sigismember(&set,SIGTSTP))
  38. printf("sigtstp\n");
  39. if(sigismember(&set,SIGTERM))
  40. printf("sigterm\n");
  41. printf("checksetend\n");
  42. }
  43. void func()
  44. {
  45. printf("hellofunc\n");
  46. }


父子进程同步到方法如下:

[cpp] view plaincopyprint?
  1. <span style="font-size:18px;"><strong>#include "apue.h"
  2. static volatile sig_atomic_t sigflag; /* set nonzero by sig handler */
  3. static sigset_t newmask, oldmask, zeromask;
  4. static void
  5. sig_usr(int signo)  /* one signal handler for SIGUSR1 and SIGUSR2 */
  6. {
  7. sigflag = 1;
  8. }
  9. void
  10. TELL_WAIT(void)
  11. {
  12. if (signal(SIGUSR1, sig_usr) == SIG_ERR)
  13. err_sys("signal(SIGUSR1) error");
  14. if (signal(SIGUSR2, sig_usr) == SIG_ERR)
  15. err_sys("signal(SIGUSR2) error");
  16. sigemptyset(&zeromask);
  17. sigemptyset(&newmask);
  18. sigaddset(&newmask, SIGUSR1);
  19. sigaddset(&newmask, SIGUSR2);
  20. /*
  21. * Block SIGUSR1 and SIGUSR2, and save current signal mask.
  22. */
  23. if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
  24. err_sys("SIG_BLOCK error");
  25. }
  26. void
  27. TELL_PARENT(pid_t pid)
  28. {
  29. kill(pid, SIGUSR2);     /* tell parent we're done */
  30. }
  31. void
  32. WAIT_PARENT(void)
  33. {
  34. while (sigflag == 0)
  35. sigsuspend(&zeromask);  /* and wait for parent */
  36. sigflag = 0;
  37. /*
  38. * Reset signal mask to original value.
  39. */
  40. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  41. err_sys("SIG_SETMASK error");
  42. }
  43. void
  44. TELL_CHILD(pid_t pid)
  45. {
  46. kill(pid, SIGUSR1);         /* tell child we're done */
  47. }
  48. void
  49. WAIT_CHILD(void)
  50. {
  51. while (sigflag == 0)
  52. sigsuspend(&zeromask);  /* and wait for child */
  53. sigflag = 0;
  54. /*
  55. * Reset signal mask to original value.
  56. */
  57. if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  58. err_sys("SIG_SETMASK error");
  59. }
  60. </strong></span>

信号操作sigsuspend相关推荐

  1. Linux进程间通信(二):信号集函数 sigemptyset()、sigprocmask()、sigpending()、sigsuspend()...

    我们已经知道,我们可以通过信号来终止进程,也可以通过信号来在进程间进行通信,程序也可以通过指定信号的关联处理函数来改变信号的默认处理方式,也可以屏蔽某些信号,使其不能传递给进程.那么我们应该如何设定我 ...

  2. sigprocmask和sigsuspend转

    有2个函数 sigprocmask和sigsuspend sigprocmask系统调用用于改变当前阻塞信号集,比如进程想阻塞SIGMIN+1信号.就把这个信号加入掩码中,然后调用 sigprocma ...

  3. sigsuspend的理解

    /* sigsuspend的使用 sigprocmask和pause连起来用可以实现sigsuspend的功能:但是还是使用sigsuspend函数,应为sigsuspend是原子操作 */ #inc ...

  4. 信号实现父子进程之间的同步--sigsuspend的作用

    函数原型: #include <signal.h> int sigsuspend(const sigset_t *mask); 作用: 用于在接收到某个信号之前,临时用mask替换进程的信 ...

  5. linux c 之sigsuspend 进程阻塞

    函数原型: #include <signal.h> int sigsuspend(const sigset_t *mask); 作用: 用于在接收到某个信号之前,临时用mask替换进程的信 ...

  6. sigsuspend的使用

    sigsupend是设置信号掩码,等待信号发生,调用 信号处理函数,恢复先前的信号掩码. 先阻塞SIGINT信号,然后用sigsuspend设置信号掩码为0(即可以处理任何信号 ),但是按组合键Ctr ...

  7. sigsuspend sigprocmask函数的用法

    一个进程的信号屏蔽字规定了当前堵塞而不能递送给该进程的信号集.调用函数sigprocmask能够检測或更改其信号屏蔽字,或者在一个步骤中同一时候运行这两个操作. #include <signal ...

  8. 信号 应用场景 内置信号 内置信号操作 自定义信号

    信号 在某些操作前后,允许特定操作 应用场景 在数据库操作前后,添加日志. 内置信号 Model signalspre_init # django的modal执行其构造方法前,自动触发post_ini ...

  9. 实验:sigsuspend(),sigprocmask()

    实验:sigsuspend(),sigprocmask() 源代码: /* * Program: pause_suspend.c * To test the difference between si ...

最新文章

  1. 扩增子分析QIIME2(2018.6). 1简介和安装
  2. iOS 开发 需要的版本管理工具,UI图,bug管理工具等
  3. 【MatConvnet速成】MatConvnet图像分类从模型自定义到测试
  4. 25道Spring框架面试题
  5. 配置Git服務器和Windows客戶端
  6. electron打包
  7. gzip: File too large错误
  8. Linux下安装配置 Jdk1.6+Tomcat5.5
  9. 【python与数据分析】Python与数据分析概述
  10. Java打印条码,使用热敏条码打印机
  11. win10笔记本电脑耳机没反应,耳机没声音的解决方法
  12. Javascript中的prototype是什么
  13. Android 购物选择颜色、尺码实现(二)
  14. 基于android的短信收发,android 短信接收短信 与发送短信源码
  15. Java学习笔记系列-入门篇-计算机基础
  16. 新员工犯错续:解决问题
  17. EDMA SEED 例程
  18. java springboot + nginx 自建 文件集群服务器
  19. lync2013之边缘服务器的部署
  20. ZT:0是不是自然数

热门文章

  1. Python数据库安装
  2. 王者荣耀连接不上服务器最新赛季排名,王者荣耀新赛季初不好上分 排位上分小技巧...
  3. Lua语法详解之多态
  4. 小米的android版本是多少合适,2019年了国产安卓里哪款手机系统最好,小米MIUI还是华为?...
  5. loadrunner controller无法创建vuser
  6. sql 给已有的表添加一个字段和备注
  7. 「Python海龟画图」利用海龟画笔绘制简易雪人
  8. 入门计算机音乐,手把手教你用电脑玩音乐之Ableton!(基础篇1)
  9. 视频直播中抖动和延迟的区别
  10. python 实现矩阵旋转