EOI(end of Interrupt):发送给可编程中断控制器的信号,指示当前中断已经处理完成。EOI信号在中断回调函数处理完成是被发送,或者PIC能够发送一个auto-Eoi在启动中断回调处理时。
APIC & 8259A
X86计算机的CPU中断只提供了两条外部引接:NMI和INTR。NMI(NonMaskable Interrupt)是不可屏蔽中断,通常用于电源掉电和物理存储器奇偶检验。INTR是可屏蔽中断,可以通过设置中断屏蔽位来屏蔽中断,主要用于接收外部硬件设备的中断信号。这些信号由中断控制器传递给CPU。
常用的中断控制器有两种:
-
可编程中断控制器8259A
-
高级可编程中断控制器(APIC)
8259A只适合单CPU的情况,为了充分挖掘SMP体系架构的并行性,能够把中断传递给系统中的每个CPU。基于此,Intel引入了一种名为I/O高级可编程控制器的新组件来替代原有的8259A。该组件包含两大部分:一是“本APIC”,主要负责传递中断信号给指定的CPU;一个具有三个CPU的机器,则它须对应有三个本地APIC。另外一个重要的部分是I/O APIC,主要负责收集来自I/O装置的interrupt信号,系统中最多可拥有8个I/O APIC。
每个本地APIC都有32位的寄存器,一个内部时钟,一个本地定时设备及本地中断保留的两条额外的IRQ线LINT0和LINT1。所有本地APIC都连接I/O APIC,形成一个多级APIC系统。如下图所示:
目前大部分单处理器系统都包含了一个I/OAPIC芯片,可以通过如下两种方式对这种芯片进行配置:
-
作为一个标准的8259A工作方式。本地APIC被禁止,外部I/O APIC连接到CPU,两条LINT0和LINT1分别连接到INTR和NMI引脚;
-
作为一个标准外部I/O APIC。本地APIC被激活,且所有的外部中断都通过I/O APIC接收。
中断分类
中断可分为同步中断和异步中断:
-
同步中断是当指令执行时由CPU控制单元产生,之所有成为同步,是因为只有在一条指令执行完毕后CPU才会发出中断,而不是发生在代码指令执行期间,比如系统调用;
-
异步中断指由其他硬件设备依照CPU时钟信号随机产生,即意味着中断能够在指令之间产生,比如键盘中断。
根据Intel官方资料,同步中断成为异常(exception),异步中断被成为中断(interrupt)。
中断可分为可屏蔽中断(MaskableInterrupt)和非屏蔽中断(Non Maskable interrupt)。异常分为故障(fault)、陷阱(trap)和终止(abort)。
从广义上讲,中断可分为四类:中断、故障、陷阱和终止。
类型 | 原因 | 异步/同步 | 返回行为 |
中断 | 来自I/O设备的信号 | 异步 | 总是返回到下一条指令 |
故障 | 潜在可修复的错误 | 同步 | 返回到当前指令 |
陷阱 | 有意的异常 | 同步 | 总是返回到下一条指令 |
终止 | 不可恢复的错误 | 同步 | 不会返回 |
X86体系结构的每个中断都被赋予一个唯一的编号或者向量(8位无符号整数)。非屏蔽中断和异常向量是固定的,而可屏蔽中断向量可以通过中断控制器的编程来改变。
中断描述表(InterruptDescriptor Table)IDT是一个系统表,它和每个中断或异常向量相关联,每个中断在表中存放的是相应的中断或者异常处理的入口地址。内核在允许中断产生前,也就是在系统初始化时,必须把IDT表的初始化地址装载到idtr寄存器中,初始化表中的每一项。
Linux中断向量分布( fromarch/x86/include/asm/irq_vectors.h)
在Linux系统中,每个CPU Core有256个IDT项,每个项有8个字节。它们是CPU执行的跳转表,当一个中断向量被触发,包括中断、故障、陷阱和终止,CPU根据IDT的地址执行相应的跳转。
在Linux启动时,将设置每个中断向量的内核跳转地址,设置后在整个系统运行期间,不会做改动。下面是IDT项的普通分布表:
向量号 | 描述 | 备注 |
0 … 31 | 系统陷阱和故障 |
|
32 … 127 | 设备中断 |
|
128 | Int 80H系统调用接口 |
|
129 …INVALIDATE_TLB_VECTOR_START-1 | 设备中断 | INVALIDATE_TLB_VECTOR_START是什么? |
INVALIDATE_TLB_VECTOR_START … 255 | 特殊中断 | 特殊中断什么意思? |
X86_64系统每个core都有一个IDT表,X86_32系统共享一个IDT表。