假定内核已被初始化,CPU在保护模式下运行
当执行了一条指令后,CS和eip这对寄存器包含下一条将要执行的指令的逻辑地址.在
处理那条指令之前,控制单元会检查在运行前一条指令时是否已经发生了一个中断或异
常。如果发生了一个中断或异常,那么控制单元执行下列操作:
1)确定与中断或异常关联的向量i (0 ≤ i ≤ 255)
2)
读由idtr寄存器指向的IDT表中的第i项(在下面的描述中,我们假定IDT表项
中包含的是一个中断门或一个陷阱门)。
3)
从gdtr寄存器获得GDT的基地址,并在GDT中查找,以读取IDT表项中的选
择符所标识的段描述符.这个描述符指定中断或异常处理程序所在段的基地址.
4)
确信中断是由授权的(中断)发生源发出的。
首先将当前特权组CPL(存放在cs寄
存器的低两位)与段描述符(存放在GDT中)的描述符特权级DPL比较,如果CPL
小于DPL. 就产生一个"Generalprotection" 异常.因为中断处理程序的特权不能
低于引起中断的程序的特权.对于编程异常,则做进一步的安全检查:比较CPL与
处于IDT中的门描述符的DPL,如果DPL小于CPL,就产生一个"General protection"
异常。这最后一个检查可以避免用户应用程序访问特殊的陷阱门或中断门.
5)
检查是否发生了特权级的变化,也就是说,CPL是否不同于所选择的段描述符的
DPL.
如果是,控制单元必须开始使用与新的特权级相关的栈。通过执行以下步骤
来做到这点:
a. 读tr寄存器,以访问运行进程的TSS段.
b. 用与新特权级相关的钱段和战指针的正确值装载ss和esp寄存器。这些值可
以在TSS中找到
c. 在新的栈中保存ss和esp以前的值. 这些值定义了与旧特权级相关的梭的逻
辑地址.
6)
如果故障已发生,用引起异常的指令地址装载cs和elp客存器,从而使得这条指令
能再次被执行。
7)
在战中保存eflags、 cs及eip的内容.
8)
如果异常产生了一个硬件出错码,则将它保存在战中.
9)
装载cs和eip寄存器,其值分别是IDT表中第i项门描述符的段选择符和偏移量
字段.这些值给出了中断或者异常处理程序的第一条指令的逻辑地址。
控制单元所执行的最后一步就是跳转到中断或者异常处理程序.换句话说.处理完中断
信号后.控制单元所执行的指令就是被选中处理程序的第一条指令.
中断或异常被处理完后,相应的处理程序必须产生一条iret指令,把控制权转交给被
中断的进程,这将迫使控制单元:
l) 用保存在校中的值装载cs、 eip或eflags寄存器。如果一个硬件出错码曾被压入校
中,并且在eip内容的上面,那么,执行iret指令前必须先弹出这个硬件出错码.
2)检查处理程序的CPL是否等于cs中最低两位的值(这意味着被中断的进程与处理
程序运行在同一特权级). 如果是,iret终止执行, 否则,转入下一步.
3)从战中装载ss和esp寄存器,因此,返回到与旧特权级相关的钱。
4)
检查ds、 es、 fs,&gs段寄存器的内容,如果其中一个寄存器包含的选择符是一
个段描述符,并且其DPL值小子CPL,那么,清相应的段寄存器.控制单元这么做
是为了禁止用户态的程序(CPL=3)利用内核以前所用的段客存器(DPL=O).如果
不清这些寄存器,怀有恶意的用户态程序就可能利用它们采访问内核地址空间.