IDT,Interrupt Descriptor Table,中断描述符表是CPU用来处理中断和程序异常的。
一 中断和IDT表概要
中断可以由硬件产生(称为外部中断),也可以由软件产生(称为内部中断),在程序中写入int n指令可以产生n号中断和异常(n从0-ffh)。
每一种中断对应一个中断号。CPU执行中断指令时,会去IDT表中查找对应的中断服务程序(interrupt service routine ,ISR)。ISR(为了表述方便用ISR n表示n号中断的处理程序),x86CPU最大可以支持256种中断。
不管运行的是什么操作系统,只要是运行于x86架构,IDT结构必然存在。IDT表中的ISRs应该由操作系统提供。
Intel指定或保留了前32个中断号的作用,操作系统可以指定其余的中断号的作用。
中断处理过程是由CPU直接调用的,CPU有专门的寄存器IDTR来保存IDT在内存中的位置。程序可以使用LIDT和SIDT指令来读写IDTR。
IDT是一个最大为256项的表,每个表项为8字节。也称为中断门。
中断门和陷阱门描述中断/异常处理程序的人口点。
二 Linux内核IDT表的初始化的基本情况
linux内核的中断描述符表IDT是一个全局的数据,在i386平台上被定义为:
struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
摘自arch/kernel/i386/traps.c;
其中每一个表项均是一个desc_struct结构,该结构被定以为:
struct desc_struct {
unsigned long a,b;
};
摘自/inlcude/asm-i386/processor.h;
可以看出IDT表共256个表项,每一个表项是8个字节,在idt_table数组被定义时静态初始化为0。
操作系统启动时,在setup32_up()函数中,会调用setup_idt()函数初始化IDT,该函数使用AT&T汇编写成,在/arch/i386/kernel/head.S中;
其主要代码如下:
......
mov $256,%ecx
rp_sidt:
movl %eax,(%edi)
movl %edx,4(%edi)
addl $8,%edi
dec %ecx
......
AT&T汇编:
movl:mov long,四个字节;
引用寄存器要在寄存器号前加百分号%, 如"movl %eax, %ebx";
使用立即数,要在数前面加符号$, 如"movl $0x04, %ebx";