10.15 sigstjmp以及siglongjmp函数

在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. [email protected]:~/UnixProgram/Chapter10$ ./10_20.exe &
  2. [3] 2566
  3. [email protected]:~/UnixProgram/Chapter10$ starting main: over
  4. kill -USR1 2566
  5. starting sig_usr1: SIHUSR1 over
  6. [email protected]:~/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. [email protected]:~/UnixProgram/Chapter10$

来自为知笔记(Wiz)

时间: 2024-12-28 13:08:01

10.15 sigstjmp以及siglongjmp函数的相关文章

APUE学习笔记——10.15 sigsetjmp和siglongjmp

转载自:sigsetjmp使用方法 如侵犯您的权益,请联系:[email protected] sigsetjmp使用方法 分类: c/c++ linux2012-02-03 12:33 1252人阅读 评论(0) 收藏 举报 signal 相关函数:longjmp, siglongjmp, setjmp 表头文件:#include <setjmp.h> 函数定义:int sigsetjmp(sigjmp_buf env, int savesigs) 函数说明:sigsetjmp()会保存眼下

信号之sigsetjmp和siglongjmp函数(转)

在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回. 但是,调用longjmp有一个问题.当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号屏蔽字中.这阻止了后来产生的这种信号中断该信号处理程序.(仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值:http://www.cnblogs.com/nufangrensheng/p/3515945.html)如果用longjmp跳出信号处理程序,那么,对此进程的信号屏蔽字会发生什么呢(

10.6 可重入函数

当一个信号捕获到并开始被进程处理的时候,进程正常执行的指令序列将被信号处理函数临时中断,进程立即转到信号处理函数中开始执行,如果信号处理函数返回(而不是调用exit或者是longjmp等),然后在进入信号处理函数之前进程正在执行的指令序列将会接着执行,但是在信号处理函数中,我们无法获知在信号被捕获的时候进程正在执行那一段代码,如果进程正在使用函数malloc在其堆上分配额外的内存的过程中会发生什么呢?或者是进程正在调用一个函数的过程中,比如说getpwnam将会发生什么呢?函数getpwnam会

c++第五版练习10.14 10.15

lambda认识:一个lambda表达式表示一个可调用的代码单元,我么可以将其理解为一个未命名的内联函数,一个lambda具有一个返回类型.一个参数列表和一个函数体 :lambda可能定义在一个函数内部. lambda的表达式:[capture list](parameter list )->return type{function body} 练习10.14 编写一个lambda ,接受两个int ,返回他们的和: #include <iostream> using namespace

CVE-2015-1328 Ubuntu 12.04, 14.04, 14.10, 15.04 overlayfs Local Root

catalog 0. 引言 1. Description 2. Effected Scope 3. Exploit Analysis 4. Principle Of Vulnerability 5. Patch Fix 0. 引言 新技术.高性能技术的不断发展,越来越提升了操作系统的能力,而近几年出现的虚拟化技术,包括overlayfs虚拟层叠文件系统技术,则为docker这样的虚拟化方案提供了越来越强大的技术支撑,但是也同时带来了很多的安全问题抛开传统的overflow溢出型漏洞不说,还有另一

macOS Catalina 10.15.4亮点在iCloud 云盘!要不要更新?先来看看更新都有哪些利弊

苹果今天发布了macOS Catalina 10.15.4正式版,增加了多项新功能.这次更新最大的变化在于 iCloud 云盘可以支持像 Dropbox.Google Drive 那样的共享文件夹功能,更便于协作和文件分享.那到底要不要更新?先来看看都更新有哪些利弊. macOS Catalina 10.15.4正式版发布增加了多项新功能.macOS Catalina 10.15.4加入了iCloud云盘文件夹共享.“屏幕使用时间”中的限定通信.Apple Music歌词实时显示等功能.本更新还

算法导论之八(10.1-5单数组实现双端队列)

算法导论第三版P131 题目: 10.1-5 栈插入和删除元素只能在同一端进行,队列的插入操作和删除操作分别在两端进行,与它们不同的,有一种双端队列(deque),其插入和删除操作都可以在两端进行.写出4个时间均为O(1)的过程,分别实现在双端队列插入和删除元素的操作,该队列使用一个数组实现的. 注意点: 1.左右端点指向的位置是类似于队列中的tail端点,是下一个插入操作的位置. 2.然后注意遍历的时候,左端点和右端点的位置关系,有两种可能,所以遍历的方式不一样. 代码: /* * 使用单数组

10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用

10.15 iptables filter表案例 10.16/10.17/10.18 iptables nat表应用 扩展 iptables应用在一个网段 http://www.aminglinux.com/bbs/thread-177-1-1.html sant,dnat,masquerade http://www.aminglinux.com/bbs/thread-7255-1-1.html iptables限制syn速率 http://www.aminglinux.com/bbs/thre

c程序设计 8.15写几个函数:①输个职工的姓名和职工号;②按职工号由小到大顺序排序,姓名顺序也随之调整;③要求输入一个职工号,用折半法找出该职工的姓名,从主函数输入要查找的职工号,输出该职工

8.15写几个函数:①输个职工的姓名和职工号:②按职工号由小到大顺序排序,姓名顺序也随之调整:③要求输入一个职工号,用折半法找出该职工的姓名, 从主函数输入要查找的职工号,输出该职工. 写的时候为方便输入,我设的是输入3名职工的信息. #define N 3 #include <stdio.h> #define N 3 #define LEN 20 //定义一个结构体类型 struct student{ char name[LEN]; int num; }; int main(){ int n