博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
10.15 sigstjmp以及siglongjmp函数
阅读量:5135 次
发布时间:2019-06-13

本文共 2220 字,大约阅读时间需要 7 分钟。

在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$

转载于:https://www.cnblogs.com/U201013687/p/5518366.html

你可能感兴趣的文章
Exception Type: IntegrityError 数据完整性错误
查看>>
《浪潮之巅》十八十九章笔记
查看>>
Power Strings
查看>>
[转载]Hash
查看>>
Nuget:Newtonsoft.Json
查看>>
你是这样理解shell编程的嘛?
查看>>
前端性能优化之重排和重绘
查看>>
Assets和Raw区别
查看>>
【luogu4185】 [USACO18JAN]MooTube [并查集]
查看>>
手机号脱敏处理
查看>>
CI控制器调用内部方法并载入相应模板的做法
查看>>
Hdu - 1002 - A + B Problem II
查看>>
HDU - 2609 - How many
查看>>
每天CookBook之Python-003
查看>>
每天CookBook之Python-004
查看>>
Android设置Gmail邮箱
查看>>
StringBuffer的用法
查看>>
js编写时间选择框
查看>>
PHP压缩文件操作
查看>>
4.你认为一些军事方面的软件系统采用什么样的开发模型比较合适?
查看>>