C语言学习:非局部跳转setjmp.h中的几个重要函数
2017-07-27 22:22
295 查看
C语言学习:非局部跳转setjmp.h中的几个重要函数
简介:
在C语言中,我们知道在一个函数的内部是可以通过goto来跳转到我们实现声明标志的地方的,但是这种跳转往往是基于函数内部实现的,而C标准库为我们提供的setjmp中,提供了setjmp,longjmp等函数,就是为了实现非局部跳转和goto的功能的。也是C语言实现异常处理的一种有效方案。
提示:
博客:章飞_906285288
博客地址:http://blog.csdn.net/qq_29924041
//setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中
//longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行。包含setjmp()宏调用的函数一定不能已经终止。所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的。
从代码的角度来展示一下
执行结果:
从上面可以看到,显示去进行注册,当longjmp发生的时候,这个函数会去第二次执行判断。这个时候走的就是else部分。
还有两个重要的函数siglongjmp和sigsetjmp:
在看这两个函数之前,可以看到这两个函数都是sig开头的,而在posix标准中,sig一般都是signal信号的意思,那这两个函数务必是于signal信号相关的。事实上也确实是。
先了解下什么是信号屏蔽字,信号屏蔽字就是进程中被阻塞的信号集, 这些信号不能发送给该进程, 它们在该进程中被”屏蔽”了. 后面我们会提到, 实际上它们是被阻塞了.也就是信号屏蔽了。
sigsetjmp和siglongjmp出现的意义是什么???在上述的sigjmp函数和longjmp函数中会有这样一个比较明显的弊端,就是当捕捉到一个信号,进入信号执行函数后,仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。会默认将此信号加入到信号屏蔽字中,这就会导致后来的这种信号对于此类信号中断该信号处理程序。而sigsetjmp和siglongjmp恰恰是为了解决这样一种场景的发生的
如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字,当用siglongjmp时,如果带 非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字。
sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,
而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序的执行。
参数env为用来保存目前堆栈环境,一般声明为全局变量
这个程序中,每次恢复栈之后,如果继续kill -12 xxx这个进程的话,依旧会持续的收到,这是因为其从信号屏蔽集中已经恢复。
注意:
在信号处理函数中的非局部跳转,尽量使用的是siglongjmp和sigsetjmp函数。使从信号处理函数中恢复到主函数中去
简介:
在C语言中,我们知道在一个函数的内部是可以通过goto来跳转到我们实现声明标志的地方的,但是这种跳转往往是基于函数内部实现的,而C标准库为我们提供的setjmp中,提供了setjmp,longjmp等函数,就是为了实现非局部跳转和goto的功能的。也是C语言实现异常处理的一种有效方案。
提示:
博客:章飞_906285288
博客地址:http://blog.csdn.net/qq_29924041
setjmp中的函数介绍:
#include <setjmp.h> int setjmp(jmp_buf env);
//setjmp()宏把当前状态信息保存到env中,供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中
void longjmp(jmp_buf env, int val);
//longjmp()用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序就象setjmp()刚刚执行完并返回非0值val那样继续执行。包含setjmp()宏调用的函数一定不能已经终止。所有可访问的对象的值都与调用longjmp()时相同,唯一的例外是,那些调用setjmp()宏的函数中的非volatile自动变量如果在调用setjmp()后有了改变,那么就变成未定义的。
从代码的角度来展示一下
/* * =========================================================================== * * Filename: jmp.cpp * Description: * Version: 1.0 * Created: 2017年07月25日 23时27分11秒 * Revision: none * Compiler: gcc * Author: (), * Company: * * =========================================================================== */ #include<iostream> //标准C语言库中的的非局部跳转 #include<setjmp.h> using namespace::std; static jmp_buf static_buf; //用来存放处理器的上下文,主要用于跳转 void jmp(){ //调用longjmp之后,会载入static_buf的处理器信息,第二个参数作为setjmp的返回值 cout << "before calling" <<endl; longjmp(static_buf,12); //12是错误的返回值,用来做差异处理 cout << "after calling "<<endl; //此句是不会执行的 } int main(int argc,char* argv[]){ int ret = 0; //将处理器信息保存到stati_buf中来,并且返回0,相当于一个标记 if((ret = setjmp(static_buf)) == 0){ cout << "first calling" << endl; jmp(); } else {//出现错误 if(ret == 12){ cout <<" error"<< endl; } } return 0; }
执行结果:
first calling before calling error
从上面可以看到,显示去进行注册,当longjmp发生的时候,这个函数会去第二次执行判断。这个时候走的就是else部分。
还有两个重要的函数siglongjmp和sigsetjmp:
在看这两个函数之前,可以看到这两个函数都是sig开头的,而在posix标准中,sig一般都是signal信号的意思,那这两个函数务必是于signal信号相关的。事实上也确实是。
先了解下什么是信号屏蔽字,信号屏蔽字就是进程中被阻塞的信号集, 这些信号不能发送给该进程, 它们在该进程中被”屏蔽”了. 后面我们会提到, 实际上它们是被阻塞了.也就是信号屏蔽了。
sigsetjmp和siglongjmp出现的意义是什么???在上述的sigjmp函数和longjmp函数中会有这样一个比较明显的弊端,就是当捕捉到一个信号,进入信号执行函数后,仅当从信号捕捉函数返回时再将进程的信号屏蔽字复位为原先值。会默认将此信号加入到信号屏蔽字中,这就会导致后来的这种信号对于此类信号中断该信号处理程序。而sigsetjmp和siglongjmp恰恰是为了解决这样一种场景的发生的
void siglongjmp(sigjmp_buf env, int val); int sigsetjmp(sigjmp_buf env, int savesigs); //如果是直接调用则返回0,如果是由于siglongjmp来调用,则返回的是非0.
如果savemask非0,则sigsetjmp在env中保存进程的当前信号屏蔽字,当用siglongjmp时,如果带 非0 savemask的sigsetjmp调用已经保存了env,则siglongjmp从其中恢复保存的信号屏蔽字。
sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,
而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序的执行。
参数env为用来保存目前堆栈环境,一般声明为全局变量
/* * =========================================================================== * * Filename: sigjmp.cpp * Description: * Version: 1.0 * Created: 2017年07月27日 21时56分33秒 * Revision: none * Compiler: gcc * Author: (), * Company: * * =========================================================================== */ #include<iostream> #include<signal.h> #include<setjmp.h> using namespace::std; static sigjmp_buf buf; void sig_handler(int signo){ cout << "before jmp" <<endl; siglongjmp(buf,10); //在收到信号的时候,调用siglongjmp,恢复堆栈信息 } int main(int argc,char *argv[]){ if(signal(SIGUSR2,sig_handler) == SIG_ERR){ //注册信号处理函数 cout << "signal error"<< endl; } int ret; ret = sigsetjmp(buf,10); //保存当前的堆栈环境,将目前的地址做一个记号 switch(ret){ case 0: cout << "first jmp" << endl; break; case 10: cout << "after jmp" << endl; break; default: break; } while(1); return 0; }
这个程序中,每次恢复栈之后,如果继续kill -12 xxx这个进程的话,依旧会持续的收到,这是因为其从信号屏蔽集中已经恢复。
注意:
在信号处理函数中的非局部跳转,尽量使用的是siglongjmp和sigsetjmp函数。使从信号处理函数中恢复到主函数中去
相关文章推荐
- 非局部跳转函数 setjmp 和 longjmp .
- C标准库学习之<setjmp.h> ——非局部跳转
- setjmp.h----非局部跳转函数
- 【C】初学习之错误处理——非局部跳转<setjmp.h>
- HEVC学习(十) —— 与变换有关的几个主要函数及重要变量
- HEVC学习(十) —— 与变换有关的几个主要函数及重要变量
- HEVC学习(十) —— 与变换有关的几个主要函数及重要变量
- R 语言学习笔记三 : 操纵数据-重要函数的使用
- 非局部跳转函数 setjmp 和 longjmp
- C语言接口与实现【第四章】 setjmp/longjmp非局部跳转函数分析
- 非局部跳转语句---setjmp和longjmp函数
- setjmp/longjmp非局部跳转函数分析
- setjmp与longjmp非局部跳转函数的使用
- Java语言学习的几个要点。
- c语言文件的几个操作函数
- Go语言学习笔记(五) [函数]
- live555学习笔记16-几个重要对象的生命期
- 函数指针2017/12/2C语言学习内容总结
- IOS 开发学习 十四 与CGRect相关的几个结构体和画图有关的几个函数
- delphi学习点滴—几个关闭函数