標籤:des style blog code ext color
只談外部中斷的windows核心管理,異常和trap不在此文的討論之列。
1. windows中斷總貌
在windows中,物理上的中斷源被抽象為KINTERRUPT結構。一個中斷源在windows中對應一個KINTERRUPT數組,數組的長度為CPU的個數,如果是單核系統,那麼這個數組長度為1。先分析KINTERRUPT結果。
windows儲存了IDT(Interrupt Descriptor Table),這張表是一個數組結構,數組的下標是Vector號(此Vector不是PIC/APIC的中斷號),數組元素8位元組,該Vector中斷的入口地址儲存在此8位元組中。再分析IDT。
PCI裝置是共用中斷,windows採用KINTERRUPT鏈表的方式組織共用中斷的裝置。結合ReactOS源碼,說明中斷掛接和中斷響應的實現過程。
2. KINTERRUPT結構
用windbg可以直接查看KINTERRUPT結構。
nt!_KINTERRUPT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x004 InterruptListEntry : _LIST_ENTRY // LIST_ENTRY是通用雙向鏈表節點,共用中斷的鏈表
+0x00c ServiceRoutine : Ptr32 unsigned char // 我們的Isr
+0x010 ServiceContext : Ptr32 Void // 暫時不清楚怎麼用
+0x014 SpinLock : Uint4B
+0x018 TickCount : Uint4B
+0x01c ActualLock : Ptr32 Uint4B
+0x020 DispatchAddress : Ptr32 void
+0x024 Vector : Uint4B // IDT表的數組下標,0~FF
+0x028 Irql : UChar
+0x029 SynchronizeIrql : UChar
+0x02a FloatingSave : UChar
+0x02b Connected : UChar // 已串連到IDT標誌
+0x02c Number : Char
+0x02d ShareVector : UChar // 共用中斷標誌
+0x030 Mode : _KINTERRUPT_MODE // 本Isr響應中斷後,是否由OS繼續調用鏈表的next Isr
+0x034 ServiceCount : Uint4B
+0x038 DispatchCount : Uint4B
+0x03c DispatchCode : [106] Uint4B // 中斷響應代碼,IDT中登記的入口地址
_LIST_ENTRY:因為核心經常用到雙向鏈表管理核心對象,windows實現了一個通用的雙向鏈表結構_LIST_ENTRY,類似Linux核心的list_header. KINTERRUPT結構內部儲存LIST_ENTRY節點,就可以將共用中斷的KINTERRUPT鏈起來。
DispatchCode:是windows的中斷響應模板,在調用Isr之前的hook。IDT登記的入口地址其實是DispatchCode的地址,等於KINTERRUPT地址+0x3C. 圖1是windbg查看IDT的內容,例如73號Vector掛在了三個裝置,入口地址(8208ddd4) 等於鏈表頭結點KINTERRUPT地址(8208dd98)+0x3C.
圖1 windbg查看IDT內容
圖2 windbg查看KINTERRUPT執行個體的內容
3. IDT(Interrupt Descriptor Table)中斷描述表
參見文章:IDT系列:(一)初探IDT,Interrupt Descriptor Table,中斷描述符表
4. 中斷掛接與響應
在毛德操的《Windows核心情景分析》9.6節中,深入ReactOS的源碼,剖析windows系統中斷管理的內幕。看原文,請看windows核心情景分析之中斷處理(毛德操)。