c語言中setjmp與longjmp(2)

2021-05-23 17:19:02 字數 2210 閱讀 2407

如何實現異常處理

首先設定乙個跳轉點(setjmp() 函式可以實現這一功能),然後在其後的**中任意地方呼叫 longjmp() 跳轉回這個跳轉點上,以此來實現當發生異常時,轉到處理異常的程式上,在其後的介紹中將介紹如何實現。 setjmp() 為跳轉返回儲存現場並為異常提供處理程式,longjmp() 則進行跳轉(丟擲異常),setjmp() 與 longjmp() 可以在函式間進行跳轉,這就像乙個全域性的 goto 語句,可以跨函式跳轉。

jmp_buf 異常結構

使用 setjmp() 及 longjmp() 函式前,需要先認識一下 jmp_buf 異常結構。jmp_buf 將使用在 setjmp() 函式中,用於儲存當前程式現場(儲存當前需要用到的暫存器的值),jmp_buf 結構在 setjmp.h 檔案內宣告:

typedef struct

jmp_buf;

jmp_buf 結構存放了程式當前暫存器的值,以確保使用 longjmp() 後可以跳回到該執行點上繼續執行。

int setjmp(jmp_buf envbuf)

void longjmp(jmp_buf envbuf,int status);

setjmp() 與 longjmp() 函式都使用了 jmp_buf 結構作為形參,它們的呼叫關係是這樣的:

首先呼叫 setjmp() 函式來初始化 jmp_buf 結構變數 jmpb,將當前cpu中的大部分影響到程式執行的積存器存入 jmpb,為 longjmp() 函式提供跳轉,setjmp() 函式是乙個有趣的函式,它能返回兩次,它應該是所有庫函式中唯一乙個能返回兩次的函式,第一次是初始化時,返回零,第二次遇到 longjmp() 函式呼叫後,longjmp() 函式使 setjmp() 函式發生第二次返回,返回值由 longjmp() 的第二個引數給出(整型,這時不應該再返回零)。

在使用 setjmp() 初始化 jmpb 後,可以其後的程式中任意地方使用 longjmp() 函式跳轉會 setjmp() 函式的位置,longjmp() 的第乙個引數便是 setjmp() 初始化的 jmpb,若想跳轉回剛才設定的 setjmp() 處,則 longjmp() 函式的第乙個引數是 setjmp() 所初始化的 jmpb 這個異常,這也說明一件事,即 jmpb 這個異常,一般需要定義為全域性變數,否則,若是區域性變數,當跨函式呼叫時就幾乎無法使用(除非每次遇到函式呼叫都將 jmpb 以引數傳遞,然而明顯地,是不值得這樣做的);longjmp() 函式的第二個引數是傳給 setjmp() 的第二次返回值。值status變成setjmp()的返回值,由此確定長調轉的來處。不允許的唯一值是0,0是程式直接呼叫函式setjmp()時由該函式返回的,不是間接通過執行函式longjmp()返回的。如果longjmp傳送的value引數值為0,那麼實際上被setjmp返回的值是1.

實現機理

setjmp()儲存其呼叫返回點的ebx, esi, edi, ebp, esp, eip,對於sigsetjmp(), 還儲存當前的訊號遮蔽字, longjmp恢復這些暫存器及訊號遮蔽字,同時傳遞乙個返回值。longjmp只是使cpu的狀態和setjmp時的狀態一致,相同的cpu初始狀態執行相同的**並不意味著產生相同的結果,setjmp, longjmp並不關心記憶體變數的變化,而只關心cpu的狀態,記憶體變數的確定性應該根據上下文來靈活處理.

如果將函式之間的呼叫關係看成一種樹型結構, 將可執行檔案的入口函式看成它的最內層節點(根節點), 那麼setjmp提供了標記節點的方法, longjmp提供了從外層節點直接返回到更內層節點的方法, 在同一層節點之間或者從內層節點到外層節點的longjmp是沒有意義的, 因為目標節點在此時根本不存在.

具體見http://www.upsdn.net/html/2004-11/47.html

還有一篇介紹的文章比較深入http://blog.codingnow.com/2010/05/setjmp.html

其中有coroutine的概念,c++中raii的概念。

一位仁兄寫的排程程式:

#include

jmp_buf jumper0,jumper1,jumper2,jumper3;

void task0()} }

void task1()} }

void task2()} }

void task3()} }

void inittask()

main()

//以上**在keil c中除錯通過

//非佔先式任務切換

//任務內變數必須是靜態的,子程式不用

//任務內不要用暫存器變數

C語言中的setjmp和longjmp

在c語言中,goto語句只能在乙個函式內實現跳轉,而不能在函式間進行跳轉。如果希望在函式間跳轉,可以使用 setjmp 和 longjmp 函式。linux 會把程序的上下文儲存在 task struct 結構體中,切換時直接恢復。而 setjmp 和 longjmp 的原理也差不多 第一次呼叫se...

C語言中的setjmp和longjmp函式

c語言的setjmp 異常處理與構建協作式多工系統 int setjmp jmp buf envbuf 巨集函式setjmp 在緩衝區envbuf中儲存系統堆疊裡的內容,供longjmp 以後使用,setjmp 必須使用標頭檔案setjmp.h。呼叫setjmp 巨集時,返回值為0,然而longjm...

c語言中的setjmp和longjmp簡介

setjmp將當前程式的執行環境儲存在乙個jump buf型別的全域性變數中 因為後續要被longjmp呼叫 第一次呼叫setjmp的返回值是null 中後續的 中執行到longjmp以後,longjmp需要兩個引數,乙個是之前setjmp儲存到執行環境的全域性變數可以調整到setjmp函式 另乙個...