中斷描述符表
能夠包含描述符。爲了構成IDT表中的一個索引值,處理器把異常或中斷的向量號乘以8。由於最多隻
有256箇中斷或異常向量,因此IDT無需包含多於256個描述符。IDT中能夠含有少於256個描述符,由於
只有可能發生的異常或中斷才須要描述符。不過IDT中全部空描述符項應該設置其存在位(標誌)爲0
// //如今這個中斷門沒有用了,設置type = 0使之空閒 // idt_addr[old_id].type = 0;
。
中含有IDT表32位的基地址和16位的長度(限長)值。IDT表基地址應該對齊在8
字節邊
界上以提升處理器的訪問效率。限長值是以
字節爲單位的IDT表的長度。
#pragma pack(push, 1) //從sidt指令得到一個以下的結構,從這裏能夠獲得IDT的開始地址 typedef struct P2C_IDTR_ { P2C_U16 limit; // 範圍 P2C_U32 base; //基地址 }P2C_IDTR, *PP2C_IDTR; #pragma pack(pop)
中斷描述符表IDT和寄存器IDTR
LIDT和SIDT指令分別用於加載和保存IDTR寄存器的內容。
LIDT指令用於把內存中的限長值和基地址操做數加載到IDTR寄存器中。該指令僅能由當前
特權級CPL是0的代碼執行,一般被用於建立IDT時的操做
系統初始化代碼中。
SIDT指令用於把IDTR中的基地址和限長內容複製到內存中。該指令可在任何特權
級上執行。
VOID *p2cGetIdt() { PAGED_CODE(); P2C_IDTR idtr; // //一句彙編讀取到IDT的位置 // _asm sidt idtr; return (void *)idtr.base; }
若是中斷或異常向量引用的描述符超過了IDT的界限,處理器會產生一個通常保護性異常
在實地址模式中,
CPU把內存中從0開始的1K字節做爲一個中斷向量表。表中的
每一個表項佔四個字節,由兩個字節的
段地址和兩個字節的
偏移量組成,這樣構成的地址即是相應
中斷處理程序的入口地址。可是,在保護模式下,由四
字節的表項構成的
中斷向量表顯然知足不了要求。這是由於,除了兩個字節的
段描述符,
偏移量必用四字節來表示;‚要有反映
模式切換的信息
在保護模式下,
中斷向量表中的表項由8個字節組成,中斷向量表也改叫作中斷描述符表IDT(InterruptDescriptor Table)。其中的每一個表項叫作一個門描述符(gate descriptor),「門」的含義是當中斷髮生時必須先經過這些門,而後才能進入相應的處理程序。
#pragma pack(push, 1) //IDT的內存空間是一個數組。每一個元素都有以下的結構 typedef struct P2C_IDT_ENTRY_ { P2C_U16 offset_low; P2C_U16 selector; P2C_U8 reserved; P2C_U8 type:4; P2C_U8 always0:1; P2C_U8 dpl:2; P2C_U8 present:1; P2C_U16 offset_high; }P2C_IDTENTRY, *PP2C_IDTENTRY; #pragma pack(pop)
主要門描述符是:
· 中斷門(Interrupt gate)
其類型碼爲110,中斷門包含了一箇中斷或
異常處理程序所在段的選擇符和段內
偏移量。當控制權經過中斷門進入
中斷處理程序時,處理器清IF標誌,即關中斷,以免嵌套中斷的發生。中斷門中的DPL(Descriptor Privilege Level)爲0,所以,用戶態的進程不能訪問Intel的中斷門。全部的
中斷處理程序都由中斷門激活,並所有限制在
內核態。
·
陷阱門(Trap gate)
其類型碼爲111,與中斷門相似,其惟一的區別是,控制權經過
陷阱門進入處理程序時維持IF標誌位不變,也就是說,不關中斷。
· 系統門(System gate)
這是Linux內核特別設置的,用來讓用戶態的進程訪問Intel的
陷阱門,所以,門描述符的DPL爲3。經過系統門來激活4個Linux
異常處理程序,它們的向量是三、四、5及128,也就是說,在用戶態下,可使用int三、into、bound 及int0x80四條
彙編指令。
最後,在保護模式下,中斷描述符表在內存的位置再也不限於從地址0開始的地方,而是能夠放在內存的任何地方。爲此,CPU中增設了一箇中斷描述符表寄存器IDTR,用來存放中斷描述符表在內存的起始地址。中斷描述符表寄存器IDTR是一個48位的寄存器,其低16位保存中斷描述符表的大小,高32位保存IDT的
基址.