中断描述符表
能够包含描述符。为了构成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的
基址.