您的位置:首页 > 运维架构 > Linux

在Linux信号处理中longjmp和siglongjmp

2016-02-10 14:54 447 查看
以下有一些是我网上搜索到的,觉得写的还行,记录下来以供以后查阅。

void longjmp(jmp_buf env, int val);

void siglongjmp(sigjmp_buf env, int val);


有一点我发现没有人说到,就是这个val,其实它是一个返回值给跳转后的setjmp指令。 但是默认返回值0 是用作第一次做记号,所以如果设置为0,页会返回1作为代替。 

相关函数:longjmp, siglongjmp, setjmp 

表头文件:#include <setjmp.h> 

函数定义:int sigsetjmp(sigjmp_buf env, int savesigs) 

函数说明:sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序好执行。 

参数env为用来保存目前堆栈环境,一般声明为全局变量 

参数savesigs若为非0则代表搁置的信号集合也会一块保存 

当sigsetjmp()返回0时代表已经做好记号上,若返回非0则代表由siglongjmp()跳转回来。 

返回值  :返回0代表局促存好目前的堆栈环境,随时可供siglongjmp()调用, 若返回非0值则代表由siglongjmp()返回

附加说明:setjmp()和sigsetjmp()会令程序不易令人理解,请尽量不要使用

Linux的异常处理

    基于setjmp和longjmp的运行控制方式是Linux平台上C语言处理异常的标准方案,已被广泛运用到由C语言开发的软件系统和链接库中,例如jpg解析库,加密解密库等等。setjmp和longjmp是以C语言标准库函数的形式提供的,setjmp函数能够保存程序当前的执行环境,即程序的状态,该被保存的程序状态可以在随后程序执行的某一点被longjmp函数恢复,程序的控制流也将跳转到调用setjmp时的执行点,实现非本地局部跳转("non-local
goto")的机制。

问题描述:

    在编写基于异常的代码混淆程序时,signal注册的异常信号处理程序只能执行一次,第二次发生异常时异常处理函数没有被调用。

分析:

1. 搞清楚Linux的信号处理流程:

  [1] 收到信号,例如SIGFPE

  [2] 进入signal注册的信号处理函数,此时,SIGFPE自动被加入到进程信号屏蔽字

  [3] 执行信号处理函数

  [4] 信号处理结束,恢复信号屏蔽字,SIGFPE被取消阻塞

  [5] 返回到产生信号地方继续执行

2. 分析异常处理函数没有被调用的原因:

    异常信号处理函数在结束前没有取消对SIGFPE信号的阻塞,直接调用longjmp()进行控制流转移。所以在后面的执行过程中再次遇到SIGFPE信号,系统会自动根据 信号屏蔽字进行屏蔽,异常处理函数也就无法被调用。

3. 该问题的解决办法:

    使用sigsetjmp和siglongjmp函数替换setjmp和longjmp函数。siglongjmp功能与longjmp类似,不同的是siglongjmp会自动恢复进程的信号屏蔽字,因此相同的异常信号再次发生时就不会被系统屏蔽了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: