#2021年底大盘点#网卡多队列

Posted 西鼠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#2021年底大盘点#网卡多队列相关的知识,希望对你有一定的参考价值。


1、什么是中断

X86体系结构的计算机采用中断机制来协同处理器与其他设备的工作。

中断本质上是一种电信号,由硬件设备生成,送入中断控制器的输入引脚中。中断控制器(如8259A)是个简单的电子芯片,将多路中断管线,采用复用技术只通过一个和处理器连接的管线和处理器通信。一个设备需要与处理器通信时,就会向处理器发出一个中断信号。例如敲击键盘时,键盘就会产生一个中断,通知操作系统有键被按下。在响应一个中断时,linux内核会调用一个叫中断处理程序的函数来处理这个中断。中断处理程序可以在中断向量表中找到,而这个中断向量表位于内存中的固定地址中。CPU处理中断后,就会恢复执行之前被中断的程序,整个流程如下图所示。

#2021年底大盘点#网卡多队列_中断处理

PS:不同设备同时中断如何知道哪个中断是来自硬盘、哪个来自网卡呢?这个很容易,系统上的每个硬件设备都会被分配一个 IRQ 号,通过这个唯一的IRQ号就能区别不同硬件设备了。

2、中断控制器

常见的中断控制有两种:

  • 可编程中断控制器 8259A
  • 高级可编程中断控制器(APIC, Advanced Programmable Interrupt Controller)

中断控制器应该在大学的硬件接口和计算机体系结构的相关课程中都学过。传统的 8259A 只适合单 CPU 的情况,现在都是多CPU多核的SMP体系,所以为了充分利用SMP体系结构、把中断传递给系统上的每个CPU 以便更好实现并行和提高性能,Intel 引入了高级可编程中断控制器(APIC)。


3、网卡收发包过程

由于中断会频繁发生,因此要求中断处理程序执行要快速。为了实现快速执行,必须要将一些繁重且不非常紧急的任务从中断处理程序中剥离出来,这一部分Linux中称为下半部,有三种方法处理下半部——软中断、tasklet和工作队列。

内核如何从网卡接受数据,传统的经典过程是这样的:

  • 数据到达网卡;
  • 网卡产生一个中断给内核;
  • 内核使用I/O指令,从网卡I/O区域中去读取数据;

第一个问题:就是如果有大流量的数据来到,网卡会产生大量的中断,内核在中断上下文中,会浪费大量的资源来处理中断本身。那么,可不可以不使用中断?这就是轮询技术(NAPI),就是内核屏蔽中断,然后隔一会儿就去问网卡是否有数据啊?从这个描述本身可以看到,如果数据量少,经常轮询同样会占用大量的不必要的CPU资源。

第二个问题:就是从网卡的I/O区域,包括I/O寄存器或I/O内存中去读取数据,这都要CPU去读,也要占用CPU资源,“CPU从I/O区域读,然后把它放到内存(这个内存指的是系统本身的物理内存,跟外设的内存不相干,也叫主内存)中”。那么,能不能让网卡直接从主内存之间读写它们的I/O数据?这就是DMA技术。具体过程是这样的。

  • 首先,内核在主内存中为收发数据建立一个环形的缓冲队列(通常叫DMA环形缓冲区)。
  • 内核将这个缓冲区通过DMA映射,把这个队列交给网卡;
  • 网卡收到数据,就直接放进这个环形缓冲区了——也就是直接放进主内存了;然后,向系统产生一个中断;
  • 内核收到这个中断,就取消DMA映射,这样,内核就直接从主内存中读取数据;

剩下的处理和操作数据包的工作就会交给软中断。在相当长的时间内,网卡的中断都是通过CPU0来处理的,造成CPU0的压力很高、其他CPU相对空闲的情况。直到网卡多队列技术的出现,网卡多队列实际就是网卡的数据请求可以通过多个CPU处理。

4、物理网卡的多队列

RSS是网卡的硬件特性,实现多队列,将不同的流分发到不同的cpu上,同一流始终在同一cpu上,避免tcp的顺序性和cpu的并行性的冲突。基于流的负载均衡,解决了顺序协议和cpu并行的冲突以及cache热度问题。如果服务器的网卡支持RSS,会在系统中看到网卡对应多个发送和接收队列:

[root@localhost ~]# ls /sys/class/net/eth0/queues/

rx-0 rx-1 rx-2 rx-3 rx-4 rx-5 rx-6 rx-7 tx-0 tx-1 tx-2 tx-3 tx-4 tx-5 tx-6 tx-7

多队列网卡的好处是可以将每个队列产生的中断分布到cpu的多个核,实现负载均衡,避免了单个核被占用到100%而其他核还处于空闲的情况。多队列网卡的每个队列的中断都是使用单独的中断线。

网卡软中断分发的软件解决方法RPS/RFS。RSS需要网卡硬件的支持,在使用不支持RSS的网卡时,为了充分利用多核cpu,centos6.1开始提供了RPS(Receive Packet Steering)和RFS(Receive Flow Steering)。

RPS使网卡可以把一个rx队列的软中断分发到多个cpu核上,从而达到负载均衡的目的。RFS是RPS的扩展,RPS只依靠hash来控制数据包,提供了好的负载平衡,但是它没有考虑应用程序的位置(注:这个位置是指程序在哪个cpu上执行)。RFS则考虑到了应用程序的位置。RFS的目标是通过指派应用线程正在运行的CPU来进行数据包处理,以此来增加数据缓存的命中率。


以上是关于#2021年底大盘点#网卡多队列的主要内容,如果未能解决你的问题,请参考以下文章

#2021年底大盘点#线程调度的方法

#2021年底大盘点#进程和线程

代码之外:人生最大的幸运就是努力没有白费#2021年底大盘点#

#2021年底大盘点#操作系统内核

#2021年底大盘点#操作系统内核

#2021年底大盘点# 常见的IO模式