setjmp和longjmp簡介

setjmp和longjmp簡介

1 setjmp和longjmp簡介

  與刺激的abort函數和exit函數相比,goto語句看起來是處理異常的更可行方案。可是goto是本地的,它只能跳到所在函數內部的標號上,而不能將控制權轉移到所在程序的任意地點(固然,除非你的全部代碼都在main體中)。 爲了解決這個限制,C函數庫提供了setjmp函數和longjmp函數,它們分別承擔非局部標號和goto做用。頭文件申明瞭這些函數及同時所需的jmpbuf數據類型。架構

  原理很是簡單:app

  1. setjmp(j)設置「jump」點,用正確的程序上下文填充jmpbuf對象j。這個上下文包括程序存放位置、棧和框架指針,其它重要的寄存器和內存數據。當初始化完jump的上下文,setjmp函數返回0值。   框架

   2.之後調用longjmp(j,r)的效果就是一個非局部的goto或「長跳轉」到由j描述的上下文處(也就是到那原來設置j的setjmp函數處)。看成爲長跳轉的目標而被調用時,setjmp()返回r或1(若是r設爲0的話)。(記住,setjmp函數不能在這種狀況時返回0。)函數

  經過有兩類返回值,setjmp函數讓你知道它正在被怎麼使用。當設置j時,setjmp函數如你指望地執行;但看成爲長跳轉的目標時,setjmp函數就從外面「喚醒」它的上下文。你能夠用longjmp函數來終止異常,用setjmp函數標記相應的異常處理程序。常見的使用方法以下所示。this

#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;
}

  最終的輸出結果以下所示。spa

''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 參考資料

  《百度百科》code

相關文章
相關標籤/搜索