- 由于 CPU 获知了计算机中发生的某些事,CPU 暂停正在执行的程序,转而去执行处理该事件的程序,当这段程序执行完毕后,CPU 继续执行刚才的程序。整个过程称为中断处理,也称为中断。
把中断按事件来源分类,来自CPU外部的中断就称为外部中断,来自CPU内部的中断就称为内部中断。
- 外部中断按是否导致宕机来划分,可分为可屏蔽中断和不可屏蔽中断。
- 内部中断按中断是否正常来划分,可分为软中断和异常。
外部中断
外部中断可分为:可屏蔽中断和不可屏蔽中断
- 外部中断是指来自CPU外部的中断,而外部的中断源必须是某个硬件,所以外部中断又称为硬件中断。CPU提供了两条信号线,外部硬件的中断是通过两根信号线通知CPU的,这两根信号线就是INTR(INTeRrupt)和 NMI(Non Maskable Interrupt)
- 可屏蔽中断:可屏蔽中断是通过INTR引脚进入CPU的,外部设备如硬盘、网卡等发出的中断都是可屏蔽中断。可屏蔽的意思是此外部设备发出的中断,CPU可以不理会,因为它不会让系统宕机,所以可以通过eflags寄存器的IF位将所有这些外部设备的中断屏蔽。另外,这些设备都是接在某个中断代理设备的,通过该中断代理也可以单独屏蔽某个设备的中断。对于这类可屏蔽中断,CPU 可以选择不用理会,甚至,即使在理会后,也可以像 Linux 那样,把中断分为上半部和下半部分开处理。
- 不可屏蔽中断:不可屏蔽中断是通过 NMI 引脚进入 CPU 的,它表示系统中发生了致命的错误,它等同于宣布:计算机的运行到此结束了。 eflags 寄存器中的 IF 位对其无效
内部中断
内部中断可分为:软中断和异常
- 软中断:软中断是由软件主动发起的中断。由于该中断是软件运行中主动发起的,所以它是主观上的,并不是客观上的内部错误
以下是可以发起中断的指令:
-
“int 8 位立即数”。这是我们以后常用的指令,我们要通过它进行系统调用,8 位立即数可表示 256种中断,这与处理器所支持的中断数是相吻合的。
-
“int3”。这可不是 int 空格 3,它们之间无间隙。int3 是调试断点指令,其所触发的中断向量号是 3,int3的机器码是0xcc。
-
into。这是中断溢出指令,它所触发的中断向量号是 4。不过,能否引发 4 号中断是要看 eflags 标志寄存器中的 OF 位是否为 1,如果是 1 才会引发中断,否则该指令悄悄地什么都不做,低调得很。
-
bound。这是检查数组索引越界指令,它可以触发 5 号中断,用于检查数组的索引下标是否在上下边界之内。该指令格式是
bound 16/32 位寄存器, 16/32 位内存
。目的操作数是用寄存器来存储的,其内容是待检测的数组下标值。。源操作数是内存,其内容是数组下标的下边界和上边界。当执行 bound 指令时,若下标处于数组索引的范围之外,则会触发 5 号中断。 -
ud2。未定义指令,这会触发第 6 号中断。该指令表示指令无效,CPU 无法识别。主动使用它发起中断,常用于软件测试中,无实际用途。
以上几种软中断指令,除第一种的“int 8 位立即数”之外,其他的几种又可以称为异常。
- 异常:异常是指令执行期间CPU内部产生的错误引起的,由于是运行时错误,所以它不受标志寄存器 eflags 中的 IF 位影响,无法向用户隐瞒(因为运行不下去了,错误兜不住了)。
- 并不是所有的异常都很致命,按照轻重程度,可以分为以下三种。:
(1) Fault,也称为故障。这种错误是可以被修复的一种类型,属于最轻的一种异常,它给软件一次“改过自新”的机会。当发生此类异常时 CPU 将机器状态恢复到异常之前的状态,之后调用中断处理程序时,CPU 将返回地址依然指向导致 fault 异常的那条指令。通常中断处理程序中会将此问题修复,待中断处理程序返回后便能重试。最典型的例子就是操作系统课程中所说的缺页异常 page fault,话说 Linux 的虚拟内存就是基于 page fault 的,这充分说明这种异常是极易被修复的,甚至是有益的。
(2) Trap,也称为陷阱,这一名称很形象地说明软件掉进了 CPU 设下的陷阱,导致停了下来。此异常通常用在调试中,比如 int3 指令便引发此类异常,为了让中断处理程序返回后能够继续向下执行,CPU将中断处理程序的返回地址指向导致异常指令的下一个指令地址。
(3) Abort,也称为终止,从名字上看,这是最严重的异常类型,一旦出现,由于错误无法修复,程序将无法继续运行,操作系统为了自保,只能将此程序从进程表中去掉。导致此异常的错误通常是硬件错误,或者某些系统数据结构出错。
向量号 | 助记符 | 说明 | 类型 | 错误号 | 产生源 |
---|---|---|---|---|---|
0 | #DE | 除 出错 | 故障 | 无 | DIV或IDIV指令 |
1 | #DB | 调试 | 故障/陷阱 | 无 | 任何代码或数据引用,或是INT 1指令 |
2 | - - | NMI中断 | 中断 | 无 | 非屏蔽外部中断 |
3 | #BP | 断点 | 陷阱 | 无 | INT 3指令 |
4 | #OF | 溢出 | 陷阱 | 无 | INTO指令 |
5 | #BR | 边界范围超出 | 故障 | 无 | BOUND指令 |
6 | #UD | 无效操作码(未定义操作码) | 故障 | 无 | UD2指令或保留的操作码(奔腾Pro中加入的新指令) |
7 | #NM | 设备不存在(无数学协处理器) | 故障 | 无 | 浮点或WAIT/FWAIT指令 |
8 | #DF | 双重错误 | 异常终止 | 有(0) | 任何可产生异常、NMI或INTR的指令 |
9 | - - | 协处理器段超越(保留) | 故障 | 无 | 浮点指令(386以后的CPU不产生该异常) |
10 | #TS | 无效的任务状态段TSS | 故障 | 有 | 任务交换或访问TSS |
11 | #NP | 段不存在 | 故障 | 有 | 加载段寄存器或访问系统段 |
12 | #SS | 堆栈错误 | 故障 | 有 | 堆栈操作和SS寄存器加载 |
13 | #GP | 一般保护错误 | 故障 | 有 | 任何内存引用和其他保护检查 |
14 | #PF | 页面保护 | 故障 | 有 | 任何内存引用 |
15 | (Intel保留,请勿使用) | 无 | |||
16 | #MF | x87FPU浮点错误(数学错误) | 故障 | 无 | x87FPU浮点或WAIT/FWAIT指令 |
17 | #AC | 对齐检查 | 故障 | 有(0) | 对内存中任何数据的引用 |
18 | #MC | 机器检查 | 异常终止 | 无 | 错误码(若有)和产生源与CPU类型有关(奔腾处理器引进) |
19 | #XM | SIMD浮点异常 | 故障 | 无 | SSE和SSE2浮点指令(PIII处理器引进) |
20~31 | - - | (Intel保留,请勿使用) | |||
32~255 | - - | 用户定义(非保留)中断 | 中断 | 外部中断或者INT n指令 |