好了,现在,我们知道了80x86微处理器在硬件级对中断和异常做了些什么,接下来,我们继续关注的是如何初始化中断描述符表。
内核启用中断以前,必须把IDT表的初始地址装到idtr寄存器,并初始化表中的每一项。这项工作是在初始化系统时完成的。
int指令允许用户态进程发出一个中断信号,其值可以是0-255的任意一个向量。因此,为了防止用户通过int指令模拟非法的中断和异常,IDT的初始化必须非常小心。这可以通过把中断或陷阱门描述符的DPL字段设置成0来实现。如果进程试图发出其中的一个中断信号,控制单元将会发现CPL的值与DPL字段有冲突,并且产生一个"General protection”异常。
然而,在少数情况下,用户态进程必须能发出一个编程异常。为此,只要把中断或陷阱门描述符的DPL字段设置成3,即特权级尽可能一样高就足够了。
现在,让我们来看一下Linux是如何实现这种策略的。
1 中断门、陷阱门及系统门
我们先回忆一下前一篇博文的“中断描述符表”,Intel提供了三种类型的中断描述符:任务门、中断门及陷阱门描述符。Linux使用与Intel稍有不同的细目分类和术语,把它们如下进行分五类:
中断门(interrupt gate):用户态的进程不能访问Intel中断门(门的DPL字段为0)。所有的Linux中断处理程序都通过中断门激活,并全部限制在内核态。
系统门(system gate):用户态的进程可以访问Intel陷阱门(门的DPL字段为3)。通过系统门来激活三个Linux异常处理程序,它们的