网卡绑定内核

  单进程、异步的I/O应该可以获得最优的通讯性能,但在现实中,我们常常发现这种模式达不到预期的效果,这可能是由于网卡在和应用程序争夺CPU资源。硬件中断的频繁发生是一件很消耗CPU资源的事情,在多CPU、多核心的条件下,如果有办法把大量硬件中断分配给特定的CPU核心进行处理,就能获得更好的性能。现在的服务器基本都是多CPU、多核心、多网卡、多硬盘,如果能分散和平衡各个中断,绑定特定的硬件中断到特定的CPU核心上,例如让网卡中断独占1个CPU 内核,磁盘I/O中断独占1个CPU核心,那么将会大大减轻单一CPU的负担,提高整体的处理效率。

1、什么是中断?

  中文教材上对“中断”的定义太生硬了,简单的说就是:每个硬件设备(如硬盘、网卡等)都需要和CPU进行某种形式的通信,以便CPU及时知道发生了什么事情,这样CPU可能就会放下手中的事情去处理应急事件,硬件设备主动打扰CPU的现象就可以称为硬件中断。就像你正在工作的时候受到QQ干扰一样,一次QQ头像闪动就可以被理解为中断。

  中断是一种比较好的CPU和硬件沟通的方式,还有一种方式叫做轮询(Polling),就是让CPU定时地对硬件状态进行查询然后做相应处理,就好像你每隔5分钟去检查一下QQ,看看有没有人找你一样,这种方式是不是很浪费时间呢?所以中断是硬件主动的方式,比轮询(CPU主动)更有效。这里又有了一个问题,每个硬件设备都中断,那么如何区分不同硬件呢?不同设备同时中断如何知道哪个中断是来自硬盘,哪个来自网卡呢?这个其实很容易,就好像每个QQ的号码都不相同,同样的,系统会为每个硬件设备分配一个IRQ号,通过这个唯一的IRQ号就能区别不同的硬件了。

  在计算机里,中断是一种电信号,由硬件产生,并直接送到中断控制器上,然后再由中断控制器向CPU发送信号,CPU检测到该信号后,就中断当前的工作转而去处理中断。然后,处理器会通知操作系统已经产生中断,这样操作系统就会对这个中断进行适当的处理。现在来看一下中断控制器,常见的中断控制器有两种:可编程中断控制器8259A和高级可编程中断控制器(APIC)。传统的8259A只适合单CPU的情况,现在都是多CPU、多核心的SMP体系,所以为了充分利用SMP体系结构,把中断传递给系统上的每个CPU以便更好实现并行和提高性能,Intel引入了高级可编程中断控制器(APIC)。

  光有高级可编程中断控制器的硬件支持还不够,Linux内核还必须能利用这些硬件的特质,所以只有kernel 2.4以后的版本才支持把不同的硬件中断请求(IRQs)分配到特定的CPU核心上,这个绑定技术被称为SMP IRQ Affinity。更多介绍请参看Linux内核源代码自带的文档:linux-2.6.31.8/Documentation/IRQ-affinity.txt。

2、如何使用?

  我们首先来了解两个基本命令:

  1. cat /proc/interrupts,查看系统上的中断情况,通常网卡的中断会被分配到CPU0上。
  2. cat cat /proc/cpuinfo,查看CPU信息,有多少CPU,有多少核心。

  然后我们使用命令来查看系统上的中断是如何分配到CPU上的,很显然CPU0上处理的中断多一些:

# cat /proc/interrupts

  CPU0 CPU1    

0:

1:

8:

9:

12:

14:

50:

58:

90:

233:

NMI:

LOC:

ERR:

MIS:

918926335

2

0

0

4

8248017

194

31673

1070374

10

5077

918809969

0

0

0

0

0

0

0

0

0

0

0

0

2032

918809894

0

0

IO-APIC-edge

IO-APIC-edge

IO-APIC-edge

IO-APIC-level

IO-APIC-edge

IO-APIC-edge

IO-APIC-level

IO-APIC-level

PCI-MSI

IO-APIC-level

 

 

 

 

timer

i8042

rtc

acpi

i8042

ide0

ohci_hcd:usb2

sata_nv

eth0

ehci_hcd:usb1

 

 

 

 

      

 

    

                                     

      

 

                

           

              

               

                      

                     

                  

  

  

 

  为了不让CPU0负载过大,如何将部分中断转移到CPU1上呢?或者说如何把eth0网卡的中断转到CPU1上呢?首先,我们需要查看一下IRQ 90(即eth0网卡的IRQ号)中断的smp affinity,看看当前中断是怎么分配在不同的CPU上的(ffffffff意味着分配在所有可用CPU上):

# cat /proc/irq/90/smp_affinity

7fffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff,ffffffff

  在进一步动手之前,我们需要先停掉IRQ自动调节的服务进程,这样才能手动绑定IRQ到不同CPU上,否则自己手动绑定做的更改将会被自动调节进程覆盖掉。如果想修改IRQ 90的中断处理,绑定到第2个CPU(CPU1)上,需要执行以下命令:

# /etc/init.d/irqbalance stop

# echo "2" > /proc/irq/90/smp_affinity

  这里需要说明一下“echo 2 > /proc/irq/90/smp_affinity”中的“2”是怎么来的。这其实是个二进制数字,代表00000010,如果00000001代表CPU0的话,那么00000010就代表 CPU1,“echo 2 > /proc/irq/90/smp_affinity”的意思就是把90中断绑定到00000010(CPU1)上。所以,各个CPU可以用二进制和十六进制表示为:

      Binary    Hex

CPU 0  00000001    1

CPU 1  00000010    2

CPU 2  00000100    4

CPU 3  00001000    8

  如果想把IRQ绑定到CPU2(即00000100=4)上,那就执行以下命令:

# echo "4" > /proc/irq/90/smp_affinity

  如果想把IRQ同时平衡到CPU0和CPU2上,即00000001+00000100=00000101=5,那就执行以下命令:

# echo "5" > /proc/irq/90/smp_affinity

  还有一个限制是,IO-APIC有两种工作模式:logic和physical。在logic模式下,IO-APIC可以同时分布同一种中断到8个CPU核心上(受到bitmask寄存器的限制,因为bitmask只有8位);在physical模式下,不能同时分布同一种中断到不同的CPU核心上,例如不能让eth0中断同时由CPU0和CPU1处理,这个时候只能定位eth0到CPU0,定位eth1到CPU1,也就是说,eth0中断不能像logic模式那样可以同时由多个CPU核心进行处理。

  过一段时间后,再查看/proc/interrupts信息,发现90: eth0在CPU1上的中断增加了145次,不断打印/proc/interrupts信息就会发现eth0在CPU0上的中断数始终保持不变,而在 CPU1上的中断数是持续增加的,这正是我们想要的结果:

# cat /proc/interrupts

  CPU0 CPU1    

0:

1:

8:

9:

12:

14:

50:

58:

90:

233:

NMI:

LOC:

ERR:

MIS:

922506515

2

0

0

4

8280147

194

31907

1073399

10

5093

922389696

0

0

0

0

0

0

0

0

0

0

145

0

2043

922389621

0

0

IO-APIC-edge

IO-APIC-edge

IO-APIC-edge

IO-APIC-level

IO-APIC-edge

IO-APIC-edge

IO-APIC-level

IO-APIC-level

PCI-MSI

IO-APIC-level

 

 

 

 

timer

i8042

rtc

acpi

i8042

ide0

ohci_hcd:usb2

sata_nv

eth0

ehci_hcd:usb1

 

 

 

 

 

      

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3、有什么用?

  在网络负载非常重的情况下,对于文件服务器、高流量Web服务器这样的应用来说,把不同的网卡IRQ均衡地绑定到不同的CPU核心上,将会减轻单个CPU的负担,提高多CPU、多核心的整体处理中断的能力。对于数据库服务器这样的应用来说,把磁盘控制器绑到一个CPU核心,把网卡绑定到另一个CPU核心上,将会提高数据库的响应时间,达到优化性能的目的。合理地根据自己的生产环境和应用的特点来平衡IRQ中断有助于提高系统的整体吞吐能力和性能。

posted @ 2013-04-07 23:09  最初的幸福ever  阅读(3042)  评论(0编辑  收藏  举报