现在的位置: 首页 > 综合 > 正文

非本地跳转的四个函数

2013年09月05日 ⁄ 综合 ⁄ 共 1066字 ⁄ 字号 评论关闭

这里讨论四个函数:setjmp, longjmp, sigsetjmp, siglongjmp

 

#include <setjmp.h>
int setjmp(jmp_buf env);
直接返回返回0,使用保存的上下文从longjmp返回返回非零。
void longjmp(jmp_buf env, int val);

 

目的:
goto可以在一个函数内跳转。jmp族函数用于非本地跳转(跨函数)。
当函数调用链很深的时候,由于出错或者其他情况,可以丢弃后续处理而直接返回到外层
逻辑,当前在栈上保存的大量局部数据都可以丢弃。调用链很深的时候一层层返回,返回
值很难组织。

在要返回到的地方调用setjmp来设置返回位置,这里setjmp是直接调用的,所以返回0。
参数env,类型是jmp_buf,这个数据类型在调用longjmp时用来存放恢复栈状态需要的所有
信息,由于需要在其他函数中访问它,通常它是一个全局变量。

调用longjmp时需要提供两个参数,第一个是调用setjmp时设置的env,第二个则是一个非
零值,设置为setjmp的返回值。使用第二个参数的原因是,这样可以一个setjmp对应多个
longjmp,通过第二个参数可以区分它们。
调用longjmp会导致对应的env的setjmp返回。

在返回以后自动变量的值是不确定的,可能是之前的值,可能是在调用链中改变以后的
值。非本地跳转不会影响全局的、静态的和volatile修饰的变量。

 

用于信号处理函数的非本地跳转
#include <setjmp.h>
int sigsetjmp(sigjmp_buf env, int savesigs);
直接返回返回0,使用保存的上下文从longjmp返回返回非零。
void siglongjmp(sigjmp_buf env, int val);

经常在信号处理函数里进行非本地跳转,返回到程序的主循环而不是返回到调用位置。
如果调用longjmp的话有一个问题:当捕捉到了一个信号,进入到信号处理程序并且当前
信号被自动加到进程的信号掩码上以防止信号嵌套。这时如果调用longjmp将会怎么样呢?
对于进程的信号掩码将会发生什么?毫无疑问,进程掩码作为全局变量将不能再被打开,
当前信号处理完成后,同样的信号将无法再次接收到。所以引进了信号处理程序中使用的
非本地跳转函数。
用于信号处理程序的非本地跳转函数的一个特点是增加了一个额外的参数savemask。如果
savemask非零,则sigsetjmp同时会将进程的当前信号掩码保存到env中,当调用siglongjmp
时,保存的信号掩码就可以恢复。

抱歉!评论已关闭.