异常就是CPU内部出现的中断,也就是说,在CPU执行特定指令时出现的非法情况。非屏蔽中断就是计算机内部硬件出错时引起的异常情况。从上图可以看出,二者与外部I/O接口没有任何关系。Intel把非屏蔽中断作为异常的一种来处理,因此,后面所提到的异常也包括了非屏蔽中断。在CPU执行一个异常处理程序时,就不再为其他异常或可屏蔽中断请求服务,也就是说,当某个异常被响应后,CPU清除eflag的中IF位,禁止任何可屏蔽中断。但如果又有异常产生,则由CPU锁存(CPU具有缓冲异常的能力),待这个异常处理完后,才响应被锁存的异常。我们这里讨论的异常中断向量在0~31之间,不包括系统调用(中断向量为0x80)。
Intel x86处理器发布了大约20种异常(具体数字与处理器模式有关)。Linux内核必须为每种异常提供一个专门的异常处理程序。这里特别说明的是,在某些异常处理程序开始执行之前,CPU控制单元会产生一个硬件错误码,内核先把这个错误码压入内核栈中。
在表3.1中给出了Pentium模型中异常的向量、名字、类型及简单描述。更多的信息可以在Intel的技术文挡中找到。
表3.1 异常的简单描述
向量 |
异常名 |
类别 |
描述 |
0 |
除法出错 |
故障 |
被0除 |
1 |
调试 |
故障/陷阱 |
当对一个程序进行逐步调试时 |
2 |
非屏蔽中断 (NMI) |
/ |
为不可屏蔽中断保留 |
3 |
断点 |
陷阱 |
由int3(断点指令)指令引起 |
4 |
溢出 |
陷阱 |
当into(check for overflow)指令被执行 |
5 |
边界检查 |
故障 |
当bound指令被执行 |
6 |
非法操作码 |
故障 |
当CPU检查到一个无效的操作码 |
7 |
设备不可用 |
故障 |
随着设置cr0的TS标志, ESCAPE或MMX指令被 执行 |
8 |
双重故障 |
故障 |
处理器不能串行处理异常而引起的 |
9 |
协处理器段越界 |
故障 |
因外部的数学协处理器引起的问题(仅用在 80386) |
10 |
无效TSS |
故障 |
要切换到的进程具有无效的TSS |
11 |
段不存在 |
故障 |
引用一个不存在的内存段 |
12 |
栈段异常 |
故障 |
试图超过栈段界限,或由ss标识的段不在内存 |
13 |
通用保护 |
故障 |
违反了Intelx86保护模式下的一个保护规则 |
14 |
页异常 |
故障 |
寻址的页不在内存,或违反了一种分页保护机制 |
15 |
Intel 保留 |
/ |
保留 |
16 |
浮点出错 |
故障 |
浮点单元用信号通知一个错误情形,如溢出。 |
17 |
对齐检查 |
故障 |
操作数的地址没有被正确地排列 |
18~31由Intel保留,为将来的扩充用