中断和异常

中断常用于处理CPU外部的异步事件异常则是处理CPU在执行过程中检测到的问题。外部中断源有两类,一类是由CPU中断引脚INTR输入的可屏蔽中断另一类是NMI引脚输入的不可屏蔽中断。异常也有两类,一类是由CPU检测到的出错、陷阱或放弃事件,另一类是编程设置的软中断比如int 3.

中断和异常编号
NMI引脚输入的不可屏蔽中断 0-31  
INTR输入的可屏蔽中断 32-47  
编程设置的软中断 48-255  
                                        注:当前系统调用使用的是0x80

 

中断描述符表(IDT)就是将上述的中断或异常标号与对应的处理程序的8字节描述符相关联的描述符数组。异常编号乘以8就可以索引到对应的描述符。描述符分为三类:任务门、中断门和陷阱门,如下图所示:

中断和异常

下面结合中断描述符介绍下中断调用的过程以及任务切换的过程

当CPU利用中断或者异常标号索引到一个IDT表的描述符后,如果这个描述符是中断门或者陷阱门,那这个调用就是一个中断过程调用;如果这个描述符是一个任务门,那这个调用过程就是一个任务切换的过程。

                                                   中断处理过程

中断调用过程:根据段选择符可以确定GDT表的段描述符,然后利用门描述符中的偏移值索引到具体的中断处理过程的开始处。

堆栈使用过程:与CALL调用(仅压入EIP)的区别是EFLAGS先入栈,然后入栈EIP。另外需要注意的是与段有关的异常,CPU会先将一个错误码压入堆栈中。

中断返回过程:IRET与RET相似,IRET为了去掉多压栈的EFLAGS会将ESP多加4;

说明:中断门和陷阱门对IF标志位的处理是不同的。中断门为了避免其他中断的干扰会复位IF,堆栈保存原值;陷阱门产生的中断不会复位IF。

                                                   任务切换过程

任务切换过程:任务门描述符中的TSS段选择符指向一个GDT表的TSS描述符,这样就间接指向一个TSS段。因此,当中断或异常指向一个任务门描述符时就会产生一次任务切换,然后在一个独立的任务中处理中断。

到这里,基本的Linux内存管理功能理论部分就介绍完了,后面会结合Linux0.11版的代码再理解一遍整个过程,欢迎继续关注。