0%

linux将网卡的 IRQ 与一个特定的 CPU 核进行绑定

中断

中断在操作系统中非常重要,它是硬件与CPU进行通信的方式,中断使得程序能从用户态陷入内核态进行系统调用。

硬件中断发生频繁,会非常消耗CPU资源。在多核CPU条件下,如果把大量硬件中断分配给不同的CPU核心处理可以很好的平衡性能。通常服务器上会有多个CPU核、多块网卡、多块硬盘,如果能让网卡中断独占1个CPU核心、磁盘IO中断独占1个CPU核心,将会大大减轻单一CPU负载、提高整体处理效率。

什么是IRQ

IRQ指的是“中断请求(Interrupt Request)”,是计算机硬件中的一种机制,用于将CPU的控制权从正在执行的程序转移到与其相关的更高优先级的事件或任务。当外部设备需要处理的事件发生时,它会向CPU发送一个中断请求信号,以引起CPU的注意并立即中断正在执行的程序,转而处理事件或任务。

在PC硬件中,IRQ通常用于处理外设的中断请求,如键盘、鼠标、网卡等。在计算机操作系统中,IRQ的处理通常由设备驱动程序负责管理。不同的IRQ号代表不同的中断请求源和优先级,例如IRQ0通常用于系统计时器,IRQ1用于键盘控制器,IRQ2用于级联PIC(可编程中断控制器),等等。

网卡绑定特定核

在Linux中,可以使用以下命令查看当前IRQ对应CPU核心的情况:

1
cat /proc/interrupts

在我的云服务器上,有如下返回值:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
IRQ_NUM     CPU0       CPU1       
0: 94 0 IO-APIC-edge timer
1: 10 0 IO-APIC-edge i8042
4: 398 0 IO-APIC-edge serial
6: 3 0 IO-APIC-edge floppy
8: 0 0 IO-APIC-edge rtc0
9: 0 0 IO-APIC-fasteoi acpi
11: 0 0 IO-APIC-fasteoi uhci_hcd:usb1, virtio2
12: 15 0 IO-APIC-edge i8042
14: 12456672 0 IO-APIC-edge ata_piix
15: 0 0 IO-APIC-edge ata_piix
24: 5 0 PCI-MSI-edge virtio0-config
25: 35425610 0 PCI-MSI-edge virtio0-input.0
26: 1 0 PCI-MSI-edge virtio0-output.0
27: 1 31636395 PCI-MSI-edge virtio0-input.1
28: 1 0 PCI-MSI-edge virtio0-output.1
29: 0 0 PCI-MSI-edge virtio1-config
30: 61771517 0 PCI-MSI-edge virtio1-req.0
NMI: 0 0 Non-maskable interrupts
LOC: 889444157 728127731 Local timer interrupts
SPU: 0 0 Spurious interrupts
PMI: 0 0 Performance monitoring interrupts
IWI: 109688740 114792299 IRQ work interrupts
RTR: 0 0 APIC ICR read retries
RES: 1062394876 1083338929 Rescheduling interrupts
CAL: 231 331 Function call interrupts
TLB: 24543172 24525287 TLB shootdowns
TRM: 0 0 Thermal event interrupts
THR: 0 0 Threshold APIC interrupts
DFR: 0 0 Deferred Error APIC interrupts
MCE: 0 0 Machine check exceptions
MCP: 42518 42518 Machine check polls
ERR: 0
MIS: 0
PIN: 0 0 Posted-interrupt notification event
NPI: 0 0 Nested posted-interrupt event
PIW: 0 0 Posted-interrupt wakeup event

假如我们想修改RTC对应的响应处理器核心,那么我们可以先通过下面的命令来获得如下返回值(其中8为RTC对应的中断号,在上面的返回值第一列可以看到):

1
cat /proc/irq/8/smp_affinity

为了说明问题,这里借用一个CPU8核的返回结果:

1
2
3
4
5
6
7
8
9
10
Binary          Hex

CPU0 0000 0001 1
CPU1 0000 0010 2
CPU2 0000 0100 4
CPU3 0000 1000 8
CPU4 0001 0000 10
CPU5 0010 0000 20
CPU6 0100 0000 40
CPU7 1000 0000 80

那么我们要设置IRQ到指定的CPU上面,可以使用如下命令:

1
echo "2" > /proc/irq/8/smp_affinity

上述命令将RTC的中断指定到CPU1核心上处理,也可以指定多个核心,如下:

1
echo "6" > /proc/irq/8/smp_affinity

/proc/irq/${IRQ_NUM}/smp_affinity为中断号为IRQ_NUM的中断绑定的CPU核的情况

而echo 后面的数字以十六进制表示,每一位代表一个CPU核

1
2
3
(00000001)代表CPU0
(00000010)代表CPU1
(00000011)代表CPU0和CPU1

有什么应用

这种方式在性能调优方面有相关应用,“中断”是机器硬件与 CPU 交互的一种方式,即硬件告诉 CPU 有事情要处理了。而网卡中断,就是机器网卡告诉 CPU 要处理网络数据了。

比如在秒杀场景中,瞬时流量非常高,带来的问题就是一下子会有非常多的网络请求进来。网卡在收到网络信号后,会通知 CPU 来处理,这时如果我们没有调整过相关配置,那么很有可能处理网卡中断的 CPU 都集中在一个核上。

如果这个时候该 CPU 也在承担处理应用进程的任务,那么就有可能出现单核 CPU 飙升的问题,同时网络数据的处理也会受到影响,导致大量 TCP 重传现象的发生。所以这个时候,我们要做的就是合理分配多核 CPU 资源,专门拿出一个核来处理网卡中断。

我们这么做的目的,其实就是在多核 CPU 下,让一个进程在某个给定的 CPU 上尽量长时间地运行而不被迁移到其他处理器。这样做的好处就是:一方面可以减少 CPU 调度产生的开销;另一方面可以提高每个 CPU 核的缓存命中率。

CPU核缓存会存哪些数据

CPU核缓存存储的数据是CPU在运行程序时频繁访问的数据和指令,它们被存储在缓存中以提高处理器的性能。缓存的容量比内存小得多,但其访问速度更快。

具体来说,CPU核缓存可以存储以下数据:

  1. 指令:存储下一条指令,以便在需要时能够快速读取。
  2. 数据:存储最近使用的数据,以便在需要时能够快速读取。
  3. 缓存行标记:用于记录缓存行中所包含的内存地址范围,以便在需要时能够快速定位。
  4. 缓存标记:用于标识缓存中的数据是否有效或已失效。
  5. 缓存控制信息:用于管理缓存的读取和写入操作,以及数据的替换和回写操作。

总之,CPU核缓存存储的数据主要是与当前运行程序相关的指令和数据,以及一些用于管理缓存的元数据。由于缓存的容量较小,因此存储在其中的数据必须经过精心的策略和算法来优化性能。

欢迎关注我的其它发布渠道