一 linux實現的幾個門
intel 提供了三種類型的中斷描述符:任務門,中斷門,陷阱門。linux稍有不同,根據intel的定義,實現了一下幾類門。
1 中斷門
使用者態的進程不能訪問的一個intel中斷門,DPL = 0。
2 系統門
使用者態的進程可以訪問的一個intel陷阱門,DPL = 3, 通過系統門可以啟用linux下的三個異常:4,5,128(即0x80)。
3 系統中斷門
使用者態的進程可以訪問的一個intel中斷門,DPL = 3,中斷異常就屬於系統中斷門,int 0x03。
4 陷阱門
使用者態的進程不能夠訪問的intel陷阱門,DPL = 0.
5 任務門
不能被使用者態進程訪問的intel任務門, DPL = 0。
二 中斷處理函數數組 interrupt[i]
在entry_32.S中的下面的彙編代碼,聲明和初始化了interrupt數組,有幾個細節值得分析。
/*interrupt數組的聲明和初始化,裡面儲存中斷處理函數的地址*/
/*interrupt數組就像c語言的數組一樣,屬於資料區段的東西,因此在資料區段聲明。但是對數組的初始化就是程式碼片段的內容了,這裡需要注意*/
.data
ENTRY(interrupt)
.text
ENTRY(irq_entries_start)
RING0_INT_FRAME
vector=0
.rept NR_IRQS
ALIGN
.if vector
CFI_ADJUST_CFA_OFFSET -4
.endif
1: pushl $~(vector)
CFI_ADJUST_CFA_OFFSET 4
jmp common_interrupt
.previous /*previous 知名下面內容上接上一個段,即data段*/
.long 1b
.text
vector=vector+1
.endr
END(irq_entries_start)
.previous
END(interrupt) /*這句是資料區段的內容*/
.previous
可以總結為:
上面一段彙編首先在資料區段聲明了一個interrupt數組,如下面代碼:
.data
ENTRY(interrupt)
.long 1b
END(interrupt)
數組中每個元素的初始值是標號1的地址。因此訪問數組中的元素時,都會跳到標號1處,執行相應的指令。
還有一個細節問題:在i8259_32.c中調用函數set_intr_gate(vector, interrupt[i]);
這裡引用了在entry_32.S中資料區段中定義的全域的interrupt數組,但是,資料區段中定義的這個intterrupt數組只能用在串連的時候,這個符號是已經定義過得,至於它的類型和大小等c編譯器無法確定,因此,在hw_irq_32.h中重新聲明了extern void (*interrupt[NR_IRQS])(void),這樣c編譯器才會確定這個數組的類型和大小。