中断其实就是由硬件或软件所发送的一种称为IRQ(中断请求)的信号。
中断允许让设备,如键盘,串口卡,并口等设备表明它们需要CPU。
一旦CPU接收了中断请求,CPU就会暂时停止执行正在运行的程序,并且调用一个称为中断处理器或中断服务程序(interrupt service routine)的特定程序。
中断服务程序或中断处理器可以在中断向量表中找到,而这个中断向量表位于内存中的固定地址中。中断被CPU处理后,就会恢复执行之前被中断的程序。
其实,在机器启动的时候,系统就已经识别了所有设备,并且也把相应的中断处理器加载到中断表中。
下面是请求CPU关注的两种方式:
1. 基于中断
2. 基于轮询
所有的linux操作系统都是基于中断驱动的。
当我们在键盘上按下一个按键时,键盘就会对CPU说,一个键已经被按下。在这种情况下,键盘的IRQ线路中的电压就会发生一次变化,而这种电压的变化就是来自设备的请求,就相当于说这个设备有一个请求需要处理。
/proc/interrupts 文件
在linux的机器上,/proc/interrupts这个文件包含有关于哪些中断正在使用和每个处理器各被中断了多少次的信息。
# cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
0: 3710374484 0 0 0 IO-APIC-edge timer
1: 20 0 0 0 IO-APIC-edge i8042
6: 5 0 0 0 IO-APIC-edge floppy
7: 0 0 0 0 IO-APIC-edge parport0
8: 0 0 0 0 IO-APIC-edge rtc
9: 0 0 0 0 IO-APIC-level acpi
12: 240 0 0 0 IO-APIC-edge i8042
14: 11200026 0 0 0 IO-APIC-edge ide0
51: 61281329 0 0 0 IO-APIC-level ioc0
59: 1 0 0 0 IO-APIC-level vmci
67: 19386473 0 0 0 IO-APIC-level eth0
75: 94595340 0 0 0 IO-APIC-level eth1
NMI: 0 0 0 0
LOC: 3737150067 3737142382 3737145101 3737144204
ERR: 0
MIS: 0
对上面文件的输出,解释如下:
● 第一列表示IRQ号
● 第二、三、四列表示相应的CPU核心被中断的次数。在上面的例子中,timer表示中断名称(为系统时钟)。3710374484表示CPU0被中断了3710374484次。i8042表示控制键盘和鼠标的键盘控制器。
● 对于像rtc(real time clock)这样的中断,CPU是不会被中断的。因为RTC存在于电子设备中,是用于追踪时间的。
● NMI和LOC是系统所使用的驱动,用户无法访问和配置。
IRQ号决定了需要被CPU处理的优先级。IRQ号越小意味着优先级越高。
例如,如果CPU同时接收了来自键盘和系统时钟的中断,那么CPU首先会服务于系统时钟,因为他的IRQ号是 0 。
● IRQ0 :系统时钟(不能改变)
● IRQ1 :键盘控制器(不能改变)
● IRQ3 :串口2的串口控制器(如有串口4,则其也使用这个中断)
● IRQ4 :串口1的串口控制器(如有串口3,则其也使用这个中断)
● IRQ5 :并口2和3 或 声卡
● IRQ6 :软盘控制器
● IRQ7 : 并口1。它被用于打印机或若是没有打印机,可以用于任何的并口。
而对于像操作杆(或称为游戏手柄)上的CPU,它并不会等待设备发送中断。因为操作杆主要用于游戏,操作杆的移动必须非常快,因此使用轮询的方式检测设备是否需要CPU的关注还是比较理想的。使用轮询方式的缺点是CPU就处于了忙等状态,因为CPU会不停的多次检查设备。但是需要注意的是在linux中,这种处理信号的方式也是必不可少的。
硬中断
对于上文所讨论的场景都是属于硬中断的例子。硬中断主要分为两种类别:
1. 非屏蔽中断(Non-maskable interrupts,即NMI):就像这种中断类型的字面意思一样,这种中断是不可能被CPU忽略或取消的。NMI是在单独的中断线路上进行发送的,它通常被用于关键性硬件发生的错误,如内存错误,风扇故障,温度传感器故障等。
2. 可屏蔽中断(Maskable interrupts):这些中断是可以被CPU忽略或延迟处理的。当缓存控制器的外部针脚被触发的时候就会产生这种类型的中断,而中断屏蔽寄存器就会将这样的中断屏蔽掉。我们可以将一个比特位设置为0,来禁用在此针脚触发的中断。