非本地跳轉的四個函數

這裏討論四個函數: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
時,保存的信號掩碼就可以恢復。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章