中断和smp_affinity
中断是通过硬件或软件发出的信号,允许设备如键盘,串口卡和并口等请求CPU处理资源。一旦CPU接收到中断请求,CPU就会临时停止运行程序的执行并调用一个称为中断处理的特殊程序,也称为ISR(中断服务程序,Interrupt Service Routine)。
中断服务或中断处理程序可以在一个中断向量表中找到定位到内存的固定地址中。在CPU处理完中断之后,CPU就会继续运行前面被中断的程序。
在启动时,系统将标记所有的设备,以及相应的中断处理被加载到内存的中断表中。
有两种获得CPU资源的方式:
基于中断
基于轮询
Linux是中断驱动的操作系统。当我们按下键盘的按键,键盘就会告知CPU某个按键已经触动。但是CPU可能正在忙于处理内存中的一些数据,系统时钟,网卡,或者视频或者PCI总线。这个例子中,键盘会在分配给硬件的IRQ流水线上放置一个电压标识事件。这个从设备的电压差的更改表示一个请求,告知CPU该设备需要处理请求。
/proc/interrupts
文件
/proc/interrupts
文件显示输出
第一列是IRQ号
第二列表示这个CPU内核被多少次中断。上例中,
[System clock]
系统时钟(名字是timer
)在CPU0上发生中断17次。rtc
([Real time clock]
)实时时钟是不能被中断的,这个设备是表示电子设备跟踪时间的。NMI
和LOC
是系统使用的驱动,用户不能访问和配置。
IRQ号表示CPU处理中断的请求的优先级,IRQ编号越小表示优先级越高。
例如,CPU同时接收到键盘和系统时钟发出的中断请求,则CPU会首先处理系统时钟,因为系统时钟的IRQ编号是0。
IRQ 0 -- 系统时钟(不能修改中断编号)
IRQ 1 -- 键盘控制器(不能修改中断编号)
IRQ 3 -- 串口2的串口控制器(和串口4共享中断)
IRQ 4 -- 串口1的串口控制器(和串口3共享中断)
IRQ 5 -- 并口2和并口3或者是声卡
IRQ 6 -- 软盘控制器
IRQ 7 -- 并口1,用于打印机
硬件中断
硬件中断分为 两大类:
不可屏蔽中断(Non-maskable interrupts,
[NMI]
):对于不可屏蔽中断CPU是不能忽略或抑制的。NMI是通过独立的中断线路发送并且NMI通常用于紧急的硬件错误,例如内存错误,风扇故障触发的硬件通知,温度传感器故障等。可屏蔽中断(Maskable interrupts):可屏蔽中断是指可以被CPU忽略或者延迟处理的中断。中断屏蔽寄存器在缓存控制器的扩展引脚上被触发屏蔽。通过写入0到一个寄存位,可以禁止这个引脚上触发中断。
软件中断
软件中断是在CPU执行一个可以在CPU [ALU unit]
自身上导致异常环境的指令所产生的中断信号。
例如,用0来除一个数是不可能的,这就会导致被0除异常,这引发计算机放弃计算或显示一个错误消息。
文件 /proc/stat
就是用来显示系统内核状态信息,也包含了一些中断信息。
显示输出
注意,这里intr
行就是每个中断号的中断发生次数(是所有cpu核处理的该中断号的次数总和)。可以对比前面cat /proc/interrupts
,例如,中断9
的总次数是8100
,在/proc/interrupts
中累加各个cpu的该中断号的中断次数就可以看到6534+259+158+14+501+39+136
= 8100
。
SMP_AFFINITY
SMP_AFFINITY
对称多处理器(symmetric multiprocessing
)是通过多个处理器处理程序的方式。smp_affinity
文件处理一个IRQ号的中断亲和性。在smp_affinity
文件结合每个IRQ号存储在/proc/irq/IRQ_NUMBER/smp_affinity
文件。这个文件中的值是一个16进制位掩码表示系统的所有CPU核。smp_affinity
在激活IO-APIC
设备驱动的设备上工作。
例如,我的笔记本使用的无线网卡设备是wlp3s0
,其中断如下
输入如下
这里wlp3s0
设备的IRQ 号是18
,相应的smp_affinity
是
显示输出
smp_affinity
是16进制表示,f就是二进制的1111
,表示4个cpu都会参与处理中断。这里ff
表示有8个cpu核心同时处理中断(实际我的笔记本是i7,双核,每个核有4个超线程)
这个中断分布的cpu核也可以从 smp_affinity_list
看到(是数字表示)
显示输出
不过,从上述/proc/interrupts
观察,虽然无线网卡中断是smp_affinity
到所有cpu核上,但是cpu0
明显分担的中断要高于其他核。
我也在线上观察了mpt2sas0
存储控制器中断 (mpt2sas0-msix0
到mpt2sas0-msix15
),发现即使smp_affinity
默认配置是ffffffff
,也就是smp_affinity_list
是0-31
,但是,从/proc/interrupts
观察,所有中断都落在cpu0
上了:
原因是没有启用irqbalance
服务,默认的的mpt2sas0-msix
队列中断都被绑定到cpu0
。后文中启动了irqbalance
服务,设置了每个mpt2sas0-msix
的中断到不同的cpu上,实现了中断分散。
居然有一种将sas控制器中断绑定到cpu的自动化方法的专利申请,实在有些无语。
IRQ Balance
irqbalance
是一个Linux工具用来将中断分散到主机的多个处理器核上帮助提高性能。irqbalance
避免所有的IRQ请求都由单一的CPU负担。很多4核以上CPU系统缓慢有时是因为都在等待CPU 0
处理网络或者存储的IRQ请求。此时CPU 0非常繁忙,而其他CPU则非常空闲。应用缓慢是因为它们在等待从CPU 0返回请求。
irqbalance
尝试一种智能方法使中断分布到所有的CPU,如果可能,将IRQ处理和处理器尽可能接近。这可能是相同的内核,和相同缓存共享的内核,或相同NUMA区域的内核。irqbalance
目标是在节能和性能优化之间找到一个平衡。
除了以下情况,你都 应该使用 irqbalance:
由于非常特殊原因需要人工设置应用/IRQ集中到特定内核(例如,更小的延迟,实时请求等)
虚拟机:虚拟机不能实际获得性能提高,因为除非你将guest绑定到特定的CPU和IRQ并且隔离网络/存储硬件,否则你看不到任何性能提高。但是你的KVM/RHEV在主机需要使用irqbalance和numa并且调优。
Numad是类似irqbalance的机制并且它将处理器和内存限定在相同的numa区域。在多核系统中,可以看到在重负载下明显降低延迟平滑的可靠的性能。
如果维护人员有很好的技术以及经常监控或者具有非常规则的负载,则可能通过人工绑定进程和IRQ到特定处理器。即使这种情况,irqbalance和numad也能达到近似的效果。所以,如果不能确定或者负载不是规律的,还是建议使用irqbalance和numad
如果系统没有安装irqbalance
,可以通过以下命令安装
安装后可以启动服务
经过一些磁盘文件操作后,可以看到前面案例中mpt2sas0
的中断开始分散到各个处理器上
检查mpt2sas0
的中断smp_affinity
:
可以看到irqbalance
启动后,调整了每个中断的smp_affinity
设置,我们可以核对一下是设置smp_affinity
是否和/proc/interrupts
观察是否一致。
举例:
中断
smp_affinity
cpu
101
000200
0000 0000 0000 0010 0000 0000
102
000100
0000 0000 0000 0001 0000 0000
103
000080
0000 0000 0000 0000 1000 0000
104
100000
0001 0000 0000 0000 0000 0000
105
008000
0000 0000 1000 0000 0000 0000
106
008000
0000 0000 1000 0000 0000 0000
107
400000
0100 0000 0000 0000 0000 0000
108
200000
0010 0000 0000 0000 0000 0000
109
000080
0000 0000 0000 0000 1000 0000
110
000800
0000 0000 0000 1000 0000 0000
111
010000
0000 0001 0000 0000 0000 0000
对于32核以上系统,用逗号分隔不连续的32核。例如,对于64核系统中IRQ 40
如果要在上述64核系统的后32核上提供IRQ 40,执行
针对消息服务器的调优 - 中断和处理进程绑定
Red Hat Entreprise MRG 是集成了消息(Messaging),实时(Realtime)和网格(Grid)服务器,其中Interrupt and process binding对中断和处理进程绑定到不同隔离的CPU以提供更好的实时响应提供了借鉴。
MRG的Messageing部分是基于Apache Qpid开源项目
以下是文档摘录翻译:
实时环境需要在响应不同的事件时最小化和消除延迟。理想情况下,中断(IRQs)和用户处理进程可以相互隔离在不同的分离的CPU上。
中断是常见的在多个CPU之间共享事件。通过写入新数据和指令缓存可以延迟中断处理,并且通常导致和其他进程争夺CPU资源。为了解决这个问题,时间敏感中断和处理进程可以分离到不同CPU或者一组CPU。这样,代码和数据结构需要处理这个具有高可能性位于处理器数据和指令缓存的中断。这个隔离的进程就可以运行得尽可能快速,而其他非时间敏感的进程可以运行在其他剩余的CPU上。这个处理在一些有些内存和总线带宽的涉及速度的环境下非常重要,此时,任何等待内存返回数据到处理器缓存的等待都会影响处理时间。
例如,在不同环境下调优程序,优化的方式完全不同。有些环境下,可能需要隔离2到4个CPU用于应用程序;另一些情况,将网络相关的应用程序处理进程绑定到CPU来处理网络驱动中断的优化。极端情况下,优化是通过尝试不同设置来发现适合工作的最优设置。
对于多处理器环境,需要了解
CPU mask
如何作用于给定CPU或一系列CPU。CPU mask
通常表述未一个32位的位掩码(bitmask)。CPU mask
可以表述为10进制或者16进制数字,取决于你使用的命令。例如,CPU0
的CPU mask
的位图表述是00000000000000000000000000000001
,10进制表述就是1
,而16进制表述就是0x00000001
。同时使用CPU0
和1
的位图表述是00000000000000000000000000000011
,10进制表述就是3
,而16进制表述就是0x00000003
。
默认情况下系统会启动 irqbalance
服务用于周期性处理CPU事件,公平方式。然而在实时环境的部署中,应用程序通常是绑定到特定的CPU上,所以不需要irqbalance
。此时,应该关闭irqbalance
另外一种方式是只在使用隔离功能的CPU上禁用irqbalance
,而在其余的CPU上继续使用irqbalance
。这个设置可以通过 /etc/sysconfig/irqbalance
来实现,即编辑 FOLLOW_ISOLCPUS
部分:
这个设置使 irqbalance
只在没有设置隔离的CPU上生效。这个设置对于只有两个处理器的主机是没有效果的,但都与双核主机是有效的。
软中断
参考 softirq
参考
Last updated