中断定义
中断是一种比较好的CPU 和硬件沟通
的方式,还有一种方式叫做轮询
(polling),就是让 CPU 定时对硬件状态进行查询然后做相应处理,这种方式非常浪费(CPU)的时间,所以中断是硬件主动
的方式,比轮询(CPU 主动)更有效一些。
每个硬件设备都中断,那么如何区分不同硬件呢?不同设备同时中断如何知道哪个中断是来自硬盘、哪个来自网卡呢?系统上的每个硬件设备都会被分配一个IRQ
号,通过这个唯一的 IRQ 号就能区别是来自谁了。
在计算机里,中断是一种电信号
,由硬件产生,并直接送到中断控制器(如 8259A)上,然后再由中断控制器向 CPU 发送信号,CPU 检测到该信号后,就中断当前的工作转而去处理中断。然后,处理器会通知操作系统已经产生中断,这样操作系统就会对这个中断进行适当的处理。现在来看一下中断控制器,常见的中断控制器有两种:可编程中断控制器 8259A 和高级可编程中断控制器(APIC),中断控制器应该在大学的硬件接口和计算机体系结构的相关课程中都学过。传统的 8259A 只适合单 CPU 的情况,现在都是多 CPU 多核的 SMP 体系,所以为了充分利用 SMP 体系结构、把中断传递给系统上的每个 CPU 以便更好实现并行和提高性能,Intel 引入了高级可编程中断控制器(APIC)。
光有高级可编程中断控制器的硬件支持还不够,Linux 内核还必须能利用到这些硬件特质,所以只有 kernel 2.4 以后的版本才支持把不同的硬件中断请求(IRQs)分配到特定的 CPU 上,这个绑定技术被称为SMP IRQ Affinity
.
如何使用
系统上的中断是怎么分配在 CPU 上的,很显然 CPU0 上处理的中断多一些
cat /proc/interrupts
CPU0 CPU1
0: 61 0 IO-APIC-edge timer
1: 15 18 IO-APIC-edge i8042
4: 4650 0 IO-APIC-edge
6: 2 0 IO-APIC-edge floppy
8: 1 0 IO-APIC-edge rtc0
9: 0 0 IO-APIC-fasteoi acpi
12: 57 6 IO-APIC-edge i8042
14: 0 0 IO-APIC-edge ata_piix
15: 133 6919 IO-APIC-edge ata_piix
16: 1700 1900 IO-APIC-fasteoi vmwgfx, snd_ens1371
17: 36636 0 IO-APIC-fasteoi ehci_hcd:usb1, ioc0
18: 75 0 IO-APIC-fasteoi uhci_hcd:usb2
19: 67 18689 IO-APIC-fasteoi ens33
24: 0 0 PCI-MSI-edge PCIe PME, pciehp
25: 0 0 PCI-MSI-edge PCIe PME, pciehp
26: 0 0 PCI-MSI-edge PCIe PME, pciehp
27: 0 0 PCI-MSI-edge PCIe PME, pciehp
28: 0 0 PCI-MSI-edge PCIe PME, pciehp
29: 0 0 PCI-MSI-edge PCIe PME, pciehp
30: 0 0 PCI-MSI-edge PCIe PME, pciehp
31: 0 0 PCI-MSI-edge PCIe PME, pciehp
32: 0 0 PCI-MSI-edge PCIe PME, pciehp
33: 0 0 PCI-MSI-edge PCIe PME, pciehp
34: 0 0 PCI-MSI-edge PCIe PME, pciehp
35: 0 0 PCI-MSI-edge PCIe PME, pciehp
36: 0 0 PCI-MSI-edge PCIe PME, pciehp
37: 0 0 PCI-MSI-edge PCIe PME, pciehp
38: 0 0 PCI-MSI-edge PCIe PME, pciehp
39: 0 0 PCI-MSI-edge PCIe PME, pciehp
40: 0 0 PCI-MSI-edge PCIe PME, pciehp
为了把部分中断转移到 CPU1 上,ehci_hcd:usb1, ioc0
的中断转到 CPU1 上呢?先查看一下 IRQ 17 中断的 smp affinity,看看当前中断是怎么分配在不同 CPU 上的(ffffffff 意味着分配在所有可用 CPU 上)
[root@kolla ~]# cat /proc/irq/17/smp_affinity
00000000,00000000,00000000,00000001
[root@kolla ~]# cat /proc/irq/17/smp_affinity_list
0
以上可知中断使用的是cpu0.
在进一步动手之前我们需要先停掉 IRQ 自动调节的服务进程,这样才能手动绑定 IRQ 到不同 CPU,否则手动绑定做的更改将会被自动调节进程给覆盖掉。如果想修改 IRQ 17 的中断处理,绑定到第2个 CPU(CPU1):
systemctl stop irqbalance
systemctl disable irqbalance
echo 1 > /proc/irq/17/smp_affinity_list ##就是指cpu1
或者
echo "2" > /proc/irq/17/smp_affinity ###2也是代指cpu1,不过需要进行二进制到16转换
###之后会讲如何计算 SMP IRQ Affinity
查看结果
[root@kolla ~]# cat /proc/irq/17/smp_affinity
00000000,00000000,00000000,00000002
过段时间在看 /proc/interrupts,是不是 17 在 CPU1 上的中断增加了、在 CPU0 上的中断没变?不断打印 /proc/interrupts 就会发现 ehci_hcd:usb1, ioc0
在 CPU0 上的中断数始终保持不变,而在 CPU1 上的中断数是持续增加
watch -d cat /proc/interrupts
Every 2.0s: cat /proc/interrupts Tue Nov 16 22:20:06 2021
CPU0 CPU1
0: 61 0 IO-APIC-edge timer
1: 15 18 IO-APIC-edge i8042
4: 10665 0 IO-APIC-edge
6: 2 0 IO-APIC-edge floppy
8: 1 0 IO-APIC-edge rtc0
9: 0 0 IO-APIC-fasteoi acpi
12: 57 6 IO-APIC-edge i8042
14: 0 0 IO-APIC-edge ata_piix
15: 133 15721 IO-APIC-edge ata_piix
16: 1700 1900 IO-APIC-fasteoi vmwgfx, snd_ens1371
17: 37417 42 IO-APIC-fasteoi ehci_hcd:usb1, ioc0
18: 75 0 IO-APIC-fasteoi uhci_hcd:usb2
19: 67 28594 IO-APIC-fasteoi ens33
24: 0 0 PCI-MSI-edge PCIe PME, pciehp