在Linux信号处理中longjmp和siglongjmp
2016-02-10 14:54
447 查看
以下有一些是我网上搜索到的,觉得写的还行,记录下来以供以后查阅。
有一点我发现没有人说到,就是这个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会自动恢复进程的信号屏蔽字,因此相同的异常信号再次发生时就不会被系统屏蔽了。
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会自动恢复进程的信号屏蔽字,因此相同的异常信号再次发生时就不会被系统屏蔽了。
相关文章推荐
- arm-linu-gcc安装
- Centos/Ubuntu环境下安装mysql
- Linux系统下的c语言编程
- 老王学linux-centos6.7heartbeat-2.1.4-12.el6.x86_64
- 【Linux学习013】文件查找
- Centos6.5分区及安装系统准备
- linux给普通用户添加root权限
- centos 6.6 hadr db2-10.5.1 express-c
- 【Linux命令】grep命令
- 【Linux命令】crontab命令
- Linux制作通用运行jar运行文件
- 老王学linux-centos6.7heartbeat-2.1.4-12.el6.x86_64
- Linux系统安装中文语言包
- linux虚拟机搭建
- linux中默认jdk的配置
- sync,fsync,fdatasync in Linux
- linux挂载/tmp目录到内存
- dup and dup2 函数 Linux
- arm学习之linux内核移植分析
- Centos 安装 Nodejs