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

信号实现父子进程之间的同步–sigsuspend的作用函数原型 include intsigsuspen constsigset t mask 作用 用于在接收到某个信号之前 临时用 mask 替换进程的信号掩码 并暂停进程执行 直到收到信号为止 The nbsp sigsuspend nbsp functionrepl

函数原型:

  #include

  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 plain   copy

  print ?

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

结果:

[cpp]  view plain   copy

  print ?

  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 plain   copy

  print ?

  1. #include 

      
      
  2. #include 

      
      
  3.     
  4. void checkset();    
  5. void func();    
  6. void main()    
  7. {    
  8.      sigset_tblockset,oldblockset,zeroset,pendmask;    
  9.      printf(“pid:%ld\n”,(long)getpid());    
  10.      signal(SIGINT,func);    
  11.     
  12.      sigemptyset(&blockset);    
  13.      sigemptyset(&zeroset);    
  14.      sigaddset(&blockset,SIGINT);    
  15.     
  16.      sigprocmask(SIG_SETMASK,&blockset,&oldblockset);    
  17.      checkset();    
  18.      sigpending(&pendmask);    
  19.     
  20.      if(sigismember(&pendmask,SIGINT))    
  21.          printf(“SIGINTpending\n”);    
  22.     
  23.      if(sigsuspend(&zeroset)!= -1)    
  24.      {    
  25.      printf(“sigsuspenderror\n”);    
  26.      exit(0);    
  27.      }    
  28.     
  29.      printf(“afterreturn\n”);    
  30.      sigprocmask(SIG_SETMASK,&oldblockset,NULL);    
  31.     
  32.      printf(“SIGINTunblocked\n”);    
  33. }    
  34.     
  35. void checkset()    
  36. {    sigset_tset;    
  37.      printf(“checksetstart:\n”);    
  38.      if(sigprocmask(0,NULL,&set)<0)    
  39.      {    
  40.      printf(“checksetsigprocmask error!!\n”);    
  41.      exit(0);    
  42.      }    
  43.     
  44.      if(sigismember(&set,SIGINT))    
  45.      printf(“sigint\n”);    
  46.     
  47.      if(sigismember(&set,SIGTSTP))    
  48.      printf(“sigtstp\n”);    
  49.     
  50.      if(sigismember(&set,SIGTERM))    
  51.      printf(“sigterm\n”);    
  52.      printf(“checksetend\n”);    
  53. }    
  54.     
  55. void func()    
  56. {    
  57.      printf(“hellofunc\n”);    
  58. }    

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/216468.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 上午11:47
下一篇 2026年3月18日 上午11:47


相关推荐

  • 为什么即梦那么快?可灵那么慢!

    为什么即梦那么快?可灵那么慢!

    2026年3月12日
    3
  • oh-my-zsh 国内安装及配置

    oh-my-zsh 国内安装及配置安装 zshubuntu 下 sudoapt getinstallzs 安装 oh my zshwgethttps gitee com mirrors oh my zsh raw master tools install sh 然后给 install sh 添加权限 chmod xinstall sh 然后执行 install sh install sh 如果发现很慢 可以修改为 gitee viminstall sh 进入编辑状态 找到以下部分 Defaultset

    2026年3月19日
    2
  • firebird修复_Firebird数据修复

    firebird修复_Firebird数据修复2014 10 15 回答深圳远标帮助您 java 可以使用 jdbc 对数据库进行读写 jdbc 访问一般分为如下流程 1 加载 jdbc 驱动程序 在连接数据库之前 首先要加载想要连接的数据库的驱动到 jvm java 虚拟机 这通过 java lang class 类的静态方法 forname stringclassn 实现 例如 try 加载 mysql 的驱动类 class forname com

    2026年3月18日
    1
  • Windows文件名长度限制

    win7x64位环境:260个长度是作为总的文件名长度限制。例如:所在文件夹的长度为50则文件名的长度被限制在210之下,超出的话会被进行截断。如果在程序中的话,超出长度的话MoveFile/CopyFile会返回错误,处理失败。例子:1.我手动在C:\建立一个文件,使用280个长度进行重命名,实际生成的却是文件名是256个

    2022年4月5日
    1.6K
  • canoe入门教程_canoe编程

    canoe入门教程_canoe编程转自:https://www.cnblogs.com/fengliu-/p/7844072.htmlCANOE入门(一)CANoe是Vector公司的针对汽车电子行业的总线分析工具,现在我用CANoe7.6版本进行介绍,其他版本功能基本差不多。硬件我使用的是CANcaseXL.1,CANoe软件的安装很简单,先装驱动,再装软件。安装完成,插上USB,连接硬件,这样在控制面板中,…

    2025年7月1日
    5
  • day2 javaee的入门知识「建议收藏」

    day2 javaee的入门知识「建议收藏」1、面向对象与面向过程的区别?面向过程的语言拥有封装、继承、多态的特性,使得整个代码灵活性高,比如Java,C++。容易维护,容易扩展。面向过程的语言直接跟内存打交道,性能要更好,比如java是需要跟虚拟机做交互,先编译解释成机器码。再跟操作系统打交道。大多数面向过程的语言基本都是直接编译成机器码在操作系统上进行执行。所以性能更好。但是java经过多年的发展,性能提升了很大,各位读者要记住javayyds!2、成员变量和局部变量的区别与c++不同的是java中没有全局变量的概念。成员变量:也称

    2022年7月8日
    21

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号