2009-12-01 40 views
9

我使用的是Ubuntu 9.10(Karmic Koala),我看了一下jmp_buf結構,它只是一個12位數組。當我使用setjmp,並通過jmp_buf結構— 12個條目中的4個被保存。這4個條目是堆棧指針,幀指針,程序計數器和返回地址。其他8個參賽作品是什麼?他們是機器相關的嗎?另一個條目是段表基址寄存器嗎?還需要什麼來正確恢復線程/進程的環境?我翻看手冊頁,其他來源,但我找不到setjmp的彙編代碼。Jmp_buf結構中的每個條目都保存了什麼?

回答

8

在MacOS X 10.6.2,頭<setjmp.h>最終使用<i386/setjmp.h>,並在那裏它說:

#if defined(__x86_64__) 
/* 
* _JBLEN is number of ints required to save the following: 
* rflags, rip, rbp, rsp, rbx, r12, r13, r14, r15... these are 8 bytes each 
* mxcsr, fp control word, sigmask... these are 4 bytes each 
* add 16 ints for future expansion needs... 
*/ 
#define _JBLEN ((9 * 2) + 3 + 16) 
typedef int jmp_buf[_JBLEN]; 
typedef int sigjmp_buf[_JBLEN + 1]; 

#else 

/* 
* _JBLEN is number of ints required to save the following: 
* eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip, 
* cs, de, es, fs, gs == 16 ints 
* onstack, mask = 2 ints 
*/ 

#define _JBLEN (18) 
typedef int jmp_buf[_JBLEN]; 
typedef int sigjmp_buf[_JBLEN + 1]; 

#endif 

你可能會發現在Linux上類似的要求 - 在jmp_buf包含足夠的信息來存儲必要的州。而且,要使用它,你實際上不需要知道它包含什麼;你所需要做的就是相信實施者正確。如果你想改變實現,那麼你當然需要理解它。

請注意,setjmp和longjmp非常特定於計算機。請閱讀Plauger的「The Standard C Library」,以便討論實施它們所涉及的一些問題。更現代化的芯片使它很難實現得很好。

4

setjmp/longjmp/sigsetjmp高度依賴CPU架構,操作系統和線程模型。在I/O錯誤或其他惡劣的情況下,前兩個函數着名(或根據您的POV而臭名昭着)(取決於您的POV)出現在原始Unix內核中,作爲「結構化」的方式來退出系統調用失敗。

結構在/usr/include/setjmp.h(Linux Fedora)中的註釋說調用環境,加上可能保存的信號掩碼。它包含/usr/include/bits/setjmp.h來聲明jmp_buf有一個由6個32位整數組成的數組,顯然特定於x86系列。

雖然我找不到除PPC implementation之外的其他源,但有合理的評論暗示應該保存FPU設置。這是有道理的,因爲未能恢復舍入模式,默認操作數大小,異常處理等將是令人驚訝的。

系統工程師通常會在這種結構中預留比實際需要更多的空間。幾個額外的字節幾乎不會出汗 - 特別是考慮到setjmp/longjmp的實際使用的稀少。太少的空間絕對是一種危險。我能想到的最顯着的原因是有額外的 - 而不是現在 - 是如果運行時庫版本更改爲需要更多的空間在jmp_buf中,通過有額外的空間已經保留,沒有必要重新編譯程序指的是它。

相關問題