码迷,mamicode.com
首页 > 其他好文 > 详细

10.15 sigstjmp以及siglongjmp函数

时间:2016-05-23 00:48:47      阅读:243      评论:0      收藏:0      [点我收藏+]

标签:


在7.10节中,我们讲述了setjmp以及longjmp函数,这两个函数用于远程跳转。其中longjmp函数进场在信号处理函数中被调用,用于返回到进程的主循环中去,而不是从信号处理函数中返回。
但是使用函数longjmp有一个问题,当一个信号被捕获的时候,信号处理函数被执行,当前信号将被自动增加到进程的信号掩码中去。这样做的目的是为了防止后续的信号中断当前信号处理函数的执行,如果我们调用longjmp函数退出信号处理函数,信号掩码将会发生什么呢?

在FreeBSD 8.0以及Mac OS X 10.6.8中,setjmp以及longjmp函数保存和恢复信号掩码,Linux 3.2.0以及Solaris 10并没有这么做,虽然Linux支持通过选项来提供BSD的行为。FreeBSD以及Mac OS X提供了函数_setjmp以及_longjmp函数,这两个函数并不保存和恢复信号掩码。
为了允许两种行为方式,POSIX.1并没有指定setjmp和longjmp函数的对于信号掩码的影响,取而代之的是,增加了两个新函数sigsetjmp以及siglongjmp函数,当从信号处理函数中进行跳转的时候一定要使用这两个函数。

  1. #include <setjmp.h>
  2. int sigsetjmp(sigjmp_buf env, int savemask);
  3. Returns:0 if called directly,nonzero if returning from a call to siglongjmp
  4. void siglongjmp(sigjmp_buf env, int val);

这两个函数与setjmp和longjmp函数的差异就是sigsetjmp有一个额外的参数。当参数savemask是非零数值的时候,sigsetjmp会将当前信号掩码一起去保存到env中,当siglongjmp函数被调用的时候,如果sigsetjmp调用的时候使用的是非零的savemask来保存的env.那么siglongjmp函数就会恢复已经保存的信号掩码。

example

  1. #include "apue.h"
  2. #include <setjmp.h>
  3. #include <time.h>
  4. static void sig_usr1(int);
  5. static void sig_alarm(int);
  6. static sigjmp_buf jmpbuf;
  7. static volatile sig_atomic_t canjump;
  8. int main(void)
  9. {
  10. if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
  11. err_sys("signal(SIGUSR1) error");
  12. if(signal(SIGALRM, sig_alarm) == SIG_ERR)
  13. err_sys("signal(SIGALRM) error");
  14. pr_mask("starting main: "); /* Figure 10.14 */
  15. if(sigsetjmp(jmpbuf, 1))
  16. {
  17. pr_mask("ending main: ");
  18. exit(0);
  19. }
  20. canjump = 1; /*now sigsetjmp() is OK*/
  21. for(;;)
  22. pause();
  23. }
  24. static void sig_usr1(int signo)
  25. {
  26. time_t starttime;
  27. if(canjump == 0)
  28. return; /*unspected signal, ignore */
  29. pr_mask("starting sig_usr1: ");
  30. alarm(3); /*SIGALRM in 3 seconds */
  31. starttime = time(NULL);
  32. for(;;)
  33. {
  34. if(time(NULL) > starttime+5)
  35. break;
  36. }
  37. pr_mask("finishing sig_usr1: ");
  38. canjump = 0;
  39. siglongjmp(jmpbuf, 1); /* jump back to main, don‘t return */
  40. }
  41. static void sig_alarm(int signo)
  42. {
  43. pr_mask("in sig_alarm: ");
  44. }

执行效果如下所示:

  1. os@debian:~/UnixProgram/Chapter10$ ./10_20.exe &
  2. [3] 2566
  3. os@debian:~/UnixProgram/Chapter10$ starting main: over
  4. kill -USR1 2566
  5. starting sig_usr1: SIHUSR1 over
  6. os@debian:~/UnixProgram/Chapter10$ in sig_alarm: SIHUSR1 SIGALRM over
  7. finishing sig_usr1: SIHUSR1 over
  8. ending main: over
  9. [3]+ Done ./10_20.exe
  10. os@debian:~/UnixProgram/Chapter10$





10.15 sigstjmp以及siglongjmp函数

标签:

原文地址:http://www.cnblogs.com/U201013687/p/5518366.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!