Linxu 中断设置

查看中断分配

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
           CPU0       CPU1       CPU2       CPU3
29: 18801666 16647304 15917474 14185149 GIC arch_timer
30: 0 0 0 0 GIC arch_timer
32: 0 0 0 0 GIC timer0
51: 0 0 0 0 GIC mmc1
52: 0 0 0 0 GIC tegra-otg, tegra-udc
53: 0 0 0 0 GIC pmc_usb_phy_wake_isr
55: 0 0 0 0 GIC tegra-sata
63: 68639 0 0 0 GIC mmc0
69: 142835 265551 0 0 GIC serial-tegra.1

71: 3748708 0 0 0 GIC tegra-xhci:usb1

97: 9260863 0 0 0 GIC host_syncpt

122: 602 0 0 0 GIC serial

131: 483307 0 0 0 GIC PCIe-MSI

642: 477100 0 0 0 PCIe-MSI eth3
643: 6232 0 0 0 PCIe-MSI iwlwifi

其中 serial-tegra.1 对应 TK1 上 /dev/ttyTHS1 的中断。第一列代表的是中断号,每个 CPU 下面的数字代表接收到的中断数。

默认情况下,系统用 CPU0 去收所有的中断。处理中断是非常耗时的任务,而系统又认为所有 CPU 的计算能力是一致的。当 CPU0 用了 30% 的资源去处理中断时,那别的 CPU 也只能发挥 70% 的计算性能,所以需要合理分配中断。

SMP/Processor affinity

Affinity 指的是任务与处理器的亲和度。如果我们一直用处理器 X 运行任务 Y,两者 affineAffine 的情况下,处理器的 cache 里会存有任务部分的 memory,所以效率是比较高的。

和一般进程相反,对中断来说,affine 到某个处理器则会导致低效。因为中断程序往往非常小,将中断程序存在 CPU 里不能改善 cache hits,而多个中断会长期占用 CPU。调度器会认为所有核都和这个中断处理核一样忙,导致其它 CPU 实际上很空闲,但是缺用不上。

APIC (Advanced Programmable Interrupt Controller)

APIC 负责分配中断,默认将所有中断交给 CPU0 处理。APIC 具有好几种传输 (delivery) 及 (destination) 模式,包括:

  • physical
  • logical
  • fixed
  • low priority

能够将中断绑到任意核上 (其实只能绑到前八个核),还能做负载均衡。

使用

  • 对某些系统来说,可能需要先停掉 irqbalance 服务
1
# /etc/init.d/irqbalance stop

对每一个中断号, /proc/irq/ 下面都有一个对应的目录,下面有一个 smp_affinity 文件,通过修改这个文件,能够改变该中断绑定的核。

文件里存的是一个 16 进制的 bitmask。哪一位为 1,就用哪个核。

比如说我们要让 CPU1 处理 TK1 的串口中断,可以这样:

1
sudo bash -c 'echo 2 > /proc/irq/69/smp_affinity'

理论上,f 能够使四个核平均处理中断。但是,实际结果还要看 APIC 是否处于 physical destination mode 及 low priority delivery mode,如果是的话才可以,可惜 TK1 不是。

  • 在内核里关掉 CONFIG_HOTPLUG_CPU 可以使 APIC 正常工作

ubuntu 可以安装一个叫 irqbalance 的东西,说不定可以解决