在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回。

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

为了允许两种形式的行为并存,POSIX.1并没有说明setjmp和longjmp对信号屏蔽字的作用,而是定义了两个新函数sigsetjmp和siglongjmp。在信号处理程序中进行非局部转移时使用这两个函数。

#include <setjmp.h>

int sigsetjmp(sigjmp_buf env, int savemask);
返回值:若直接调用则返回0,若从siglongjmp调用返回则返回非0值 void siglongjmp(sigjmp_buf env, int val);

这两个函数与setjmp和longjmp之间的唯一区别是sigsetjmp增加了一个参数。如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字调用siglongjmp时,如果带 非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字

 

实例

程序清单10-14演示了在信号处理程序被调用时,系统所设置的信号屏蔽字如果自动地包括刚被捕捉到的信号。该程序也通过实例说明了如何使用sigsetjmp和siglongjmp函数。

程序清单10-14 信号屏蔽字、sigsetjmp和siglongjmp实例

#include "apue.h"
#include <setjmp.h>
#include <time.h> static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjump; int
main(void)
{
if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error"); if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error"); pr_mask("starting main: "); if (sigsetjmp(jmpbuf, 1))
{
pr_mask("ending main: ");
exit(0);
}
canjump = 1; /* now sigsetjmp() is OK */ for(; ;)
pause();
} static void
sig_usr1(int signo)
{
time_t starttime; if (canjump == 0)
return; /* unexpected signal, ignore */ pr_mask("starting sig_usr1: ");
alarm(3); /* SIGALRM in 3 seconds */
starttime = time(NULL);
for(; ;) /* busy wait for 5 seconds */
if (time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: "); canjump = 0;
siglongjmp(jmpbuf, 1); /* jump back to main, don't return */
} static void
sig_alrm(int signo)
{
pr_mask("in sig_alrm: ");
}

pr_mask函数参见:http://www.cnblogs.com/nufangrensheng/p/3515257.html中程序清单10-10

此程序演示了另一种技术,只要在信号处理程序中调用siglongjmp,就应使用这种技术:仅在调用sigsetjmp之后才将变量canjump设置为非0值。在信号处理程序中检测此变量,仅当它为非0值时才调用siglongjmp。这提供了一种保护机制,使得在jmpbuf(跳转缓冲)尚未由sigsetjmp初始化时,防止调用信号处理程序。在一般的C代码中(不是信号处理程序),对于longjmp并不需要这种保护措施。但是,因为信号可能在任何时候发生,所以在信号处理程序中,需要这种保护措施。

在程序中使用了数据类型sig_atomic_t,这是由ISO C标准定义的变量类型,在写这种类型的变量时不会被中断。这种类型的变量总是包括ISO类型修饰符voaltile。

在RedHat Linux 2.6.18版本中执行程序清单10-14并没有出现我们所预期的结果:当调用一个信号处理程序时,被捕捉到的信号加到进程的当前信号屏蔽字中。当从信号处理程序返回时,恢复原来的屏蔽字。不知为何???

从上面运行结果可以看出,信号屏蔽字始终都是空。本来应该是在调用一个信号处理程序时,被捕捉到的信号加到进程的当前信号屏蔽字中。为啥没有加进去呢?还是加进去了没有更新信号屏蔽字呢?

本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

信号之sigsetjmp和siglongjmp函数的更多相关文章

  1. 信号之sigsetjmp和siglongjmp函数(转)

    在信号处理程序中经常调用longjmp函数以返回到程序的主循环中,而不是从该处理程序返回. 但是,调用longjmp有一个问题.当捕捉到一个信号时,进入信号捕捉函数,此时当前信号被自动地加到进程的信号 ...

  2. signal函数、sigaction函数及信号集(sigemptyset,sigaddset)操作函数

    信号是与一定的进程相联系的.也就是说,一个进程可以决定在进程中对哪些信号进行什 么样的处理.例如,一个进程可以忽略某些信号而只处理其他一些信号:另外,一个进程还可以选择如何处理信号.总之,这些总与特定 ...

  3. UNIX环境高级编程——信号基本概述和signal函数

    一.为了理解信号,先从我们最熟悉的场景说起:1. 用户输入命令,在Shell下启动一个前台进程.2. 用户按下Ctrl-C,这个键盘输入产生一个硬件中断.3. 如果CPU当前正在执行这个进程的代码,则 ...

  4. 三十一、Linux 进程与信号——SIGCHLD 信号、kill和raise函数以及alarm函数

    31.1 SIGCHLD 信号 子进程状态发生变化(子进程结束)产生该信号,父进程需要使用 wait 调用来等待子进程结束并回收它. 避免僵尸进程 #include <stdio.h> # ...

  5. 三十、Linux 进程与信号——信号的概念及 signal 函数

    30.1 信号的基本概念 信号(signal)机制是Linux 系统中最为古老的进程之间的通信机制,解决进程在正常运行过程中被中断的问题,导致进程的处理流程会发生变化 信号是软件中断 信号是异步事件 ...

  6. 信号的捕捉与sigaction函数

    一.内核如何实现信号的捕捉 如果信号的处理动作是用户自定义函数,在信号递达时就调用这个函数,这称为捕捉信号.由于信号处理函数的代码是在用户空间的,处理过程比较复杂,举例如下: 1. 用户程序注册了SI ...

  7. Linux信号、信号处理和信号处理函数

    信号(signal)是一种软件中断,它提供了一种处理异步事件的方法,也是进程间惟一的异步通信方式.在Linux系统中,根据POSIX标准扩展以后的信号机制,不仅可以用来通知某种程序发生了什么事件,还可 ...

  8. APUE学习笔记——10.15 sigsetjmp和siglongjmp

    转载自:sigsetjmp使用方法 如侵犯您的权益,请联系:windeal12@qq.com sigsetjmp使用方法 分类: c/c++ linux2012-02-03 12:33 1252人阅读 ...

  9. Linux 信号(二)—— signal 函数

    弗洛伊德认为:要解决这些苦恼,当事人就要通过回忆并理解自己早期的童年经历,来获得对潜意识冲突的顿悟.弗洛伊德的疗法被称为“精神分析” (psychoanalysis),在 20 世纪的很长一段时间被心 ...

随机推荐

  1. MySQL索引的查看创建和删除

    1.索引作用 在索引列上,除了上面提到的有序查找之外,数据库利用各种各样的快速定位技术,能够大大提高查询效率.特别是当数据量非常大,查询涉及多个表时,使用索引往往能使查询速度加快成千上万倍. 例如,有 ...

  2. 使用Amoeba 实现MySQL DB 读写分离

    Amoeba(变形虫)项目是一个开源框架,于2008年开始发布一款 Amoeba for Mysql软件: 这个软件致力于MySQL的分布式数据库前端代理层,它主要在应用层访问MySQL的时候充当SQ ...

  3. 解决angular的post请求后SpringMVC后台接收不到参数值问题的方法

    这是我后台SpringMVC控制器接收isform参数的方法,只是简单的打出它的值: @RequestMapping(method = RequestMethod.POST) @ResponseBod ...

  4. POJ 3281 Dining (网络流构图)

    [题意]有F种食物和D种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一种食物和一种饮料.现在有N头牛,每头牛都有自己喜欢的食物种类列表和饮料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和 ...

  5. Welcome to Linux From Scratch!

    /**************************************************************************** * Welcome to Linux Fro ...

  6. SqlSugar轻量ORM

      蓝灯软件数据股份有限公司项目,代码开源. SqlSugar是一款轻量级的MSSQL ORM ,除了具有媲美ADO的性能外还具有和EF相似简单易用的语法. 学习列表 0.功能更新 1.SqlSuga ...

  7. Today I Cooked the Sun Yat-Sen University [2007-09-25 12:37:39]

    Aha,yes,it is! And I paticipate in the school page of sysu...and cann't change my previous csu to sy ...

  8. STL sort()函数

    C++之所以得到这么多人的喜欢,是因为它既具有面向对象的概念,又保持了C语言高效的特点.STL 排序算法同样需要保持高效.因此,对于不同的需求,STL提供的不同的函数,不同的函数,实现的算法又不尽相同 ...

  9. CXF之二(CXF发布webService)

    Apache CXF提供了用于方便地构建和开发WebService的可靠基础架构.它允许创建高性能和可扩展的服务,可以部署在Tomcat和基于spring的轻量级容器中,也可以部署在更高级的服务器上, ...

  10. NOIP2006 能量项链

    洛谷1063 能量项链 本题地址:http://www.luogu.org/problem/show?pid=1063 题目描述 在Mars星球上,每个Mars人都随身佩带着一串能量项链.在项链上有N ...