setjmp和longjmp简介
1 setjmp和longjmp简介
与刺激的abort函数和exit函数相比,goto语句看起来是处理异常的更可行方案。但是goto是本地的,它只能跳到所在函数内部的标号上,而不能将控制权转移到所在程序的任意地点(当然,除非你的所有代码都在main体中)。
为了解决这个限制,C函数库提供了setjmp函数和longjmp函数,它们分别承担非局部标号和goto作用。头文件
#include <setjmp.h>
#include <stdio.h>
jmp_buf j;
void raise_exception(void)
{
printf("exception raised\n");
longjmp(j, 3); /* jump to exception handler case 3 */
printf("this line should never appear\n");
}
int main(void)
{
switch (setjmp(j)) {
case 0:
printf("''setjmp'' is initializing ''j''\n");
raise_exception();
printf("this line should never appear\n");
case 1:
printf("Case 1\n");break;
case 2:
printf("Case 2\n");break;
case 3:
printf("Case 3\n");break;
default:
break;
}
return 0;
}
最终的输出结果如下所示。
''setjmp'' is initializing ''j''
exception raised
Case 3
2 SylixOS下实现
SylixOS未使用C库中的setjmp与longjmp函数,而是重新在各个架构中实现。如MIPS架构便是在/libsyllixos/SylixOS/arch/mips/common/mipsLibAsm.S文件中实现这两个函数,其代码如下所示。
;/**************************************************************************
; sigsetjmp (参数为 jmp_buf, mask_saved)
;**************************************************************************/
FUNC_DEF(sigsetjmp)
CALL_SETUP __sigsetjmpSetup
SAVE_NON_VOLATILE_REG
JR RA
MOV V0 , ZERO
FUNC_END(sigsetjmp)
;/**************************************************************************
; longjmp (参数为 jmp_buf, retval)
;**************************************************************************/
FUNC_DEF(longjmp)
CALL_SETUP __longjmpSetup
RESTORE_NON_VOLATILE_REG
MOV V0 , A1
BNE V0 , ZERO , longjmpnotzero
NOP
LI V0 , 1
LINE_LABEL(longjmpnotzero)
JR RA
NOP
FUNC_END(longjmp)
3 参考资料
《百度百科》