中斷描述符表(Interrupt Descriptor Table,IDT)


中斷描述符表(Interrupt Descriptor Table,IDT)將每個異常或 中斷向量分別與它們的處理過程聯系起來。與GDT和LDT表類似,IDT也是由8字節長描述符組成的一個數組。
#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)

 

中斷描述符表
可以包含描述符。為了構成IDT表中的一個索引值,處理器把異常或中斷的向量號乘以8。因為最多只
有256個中斷或異常向量,所以IDT無需包含多於256個描述符。IDT中可以含有少於256個描述符,因為
只有可能發生的異常或中斷才需要描述符。不過IDT中所有空描述符項應該設置其存在位(標志)為0
//
//現在這個中斷門沒有用了,設置type = 0使之空閑
//
idt_addr[old_id].type = 0;
IDT表可以駐留在線性 地址空間的任何地方,處理器使用IDTR 寄存器來定位IDT表的位置。這個寄存器
中含有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 異常處理程序,它們的向量是3、4、5及128,也就是說,在用戶態下,可以使用int3、into、bound 及int0x80四條 匯編指令
最后,在保護模式下,中斷描述符表在內存的位置不再限於從地址0開始的地方,而是可以放在內存的任何地方。為此,CPU中增設了一個中斷描述符表寄存器IDTR,用來存放中斷描述符表在內存的起始地址。中斷描述符表寄存器IDTR是一個48位的寄存器,其低16位保存中斷描述符表的大小,高32位保存IDT的 基址.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM