天天看点

中断描述符表IDT以及Linux内核IDT表的初始化的基本情况

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";

继续阅读