linux rps(linux系统哪个好用)
各位老铁们,大家好,今天由我来为大家分享linux rps,以及linux系统哪个好用的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!
关于linux 软中断对网卡性能的影响以及优化
首先,要对软中断有一个认识,程序运行后,操作系统会发送程序需要的一些cpu指令到某个cpu,扔给CPU的这个过程是异步的,cpu获得指令后操作完成会触发一个硬中断,并且把操作的结果保存在寄存器,之后linux内核会启动ksofttrip进程去,来获取操作结果,这个动作就叫做软中断。
linux默认会起n个ksofttrip进程,n等于cpu的个数,ksofttrip是死循环,只要有软中断,它就会一直去获取,n个ksoftrip获取源是一样的,为什么要起n个进程呢?就是为了,当某个cpu空闲,哪个就去跑。通常操作系统里它的进程名是 ksoftrip/n,n是对应的cpu的编号,ksoft进程跟cpu是一对一绑定的。
现在来说说网卡的性能问题,要想优化,首先你的网卡必须是多通道队列的。那如何知道你的网卡是否是多队列的呢?通过cat/proc/interrept|grep eth0|wc-l可以看到网卡通道队列的数量.
现在来来说说优化方案,为什么要优化,因为linux默认情况所有的网卡的软中断都是的cpu0,所以加入你的ksoftrip/0总是跑满,就说明可能是网卡问题了。
方案1,SMP IRQ affinity技术
说白了,就是信号量分布技术,把特定信号量的处理放到固定的cpu上,每个网卡的通道队列都有一个自己的信号量。
首先查看所有网卡通道队列的信号量,方法 cat/proc/interrept|grep eth0
每行最开头的数字“n:”就是信号量,在/proc/irq/下面可以找到对应的以信号量命名的目录
找完了之后,可以进行信号量绑定了,在/proc/irq/n/下面有两个文件,分别是smp_affinity跟smp_affinity_list,这两个是文件的内容是对应的,smp_affinity里是通过bitmask算法绑定cpu,smp_affinity_list是通过数字指定cpu编号的方法,例如 cpu0,文件里就是“0”,如果是cpu1跟2就是“1,2”
!!重点来了,虽然默认里面填写的是多个,但是!!!但是它只跑在绑定cpu中的第一个!!!坑啊!!!
所以,你要做的就是单独绑定每一个网卡的通道队列。
直接echo"1">/proc/irq/(cpu1的信号量)/snmp_affinity_list
echo"3">/proc/irq/$(cpu2的信号量)/snmp_affinity_list
这个是最快速的解决方案,提升效率显著啊!!!
升级方案2,在方案1基础之上,RPS/RFS技术
此技术大家可以查网上,文章很多,优化效果是,单个网卡通道队列的软中断会平均到所有cpu上,并且会优化为,中断落在发出中断的程序所在的那个cpu上,这样节省了cpu cache。
坏消息是对单队列网卡而言,「smp_affinity」和「smp_affinity_list」配置多CPU无效。
好消息是Linux支持RPS,通俗点来说就是在软件层面模拟实现硬件的多队列网卡功能。
首先看看如何配置RPS,如果CPU个数是 8个的话,可以设置成 ff:
shell> echo ff>/sys/class/net/eth0/queues/rx-0/rps_cpus
接着配置内核参数rps_sock_flow_entries(官方文档推荐设置: 32768):
shell> sysctl net.core.rps_sock_flow_entries=32768
最后配置rps_flow_cnt,单队列网卡的话设置成rps_sock_flow_entries即可:
echo 32768>/sys/class/net/eth0/queues/rx-0/rps_flow_cnt
说明:如果是多队列网卡,那么就按照队列数量设置成 rps_sock_flow_entries/ N。
一文看懂linux 内核网络中 RPS/RFS 原理
Linux内核中的RPS/RFS原理解析
在理解Linux内核网络中RPS(Round Robin Packet Scheduling)和RFS(Round Robin Flow Scheduling)原理之前,需先认识到基于简单中断负载均衡(如系统自带的irqbalance进程)可能产生的问题。这些负载均衡器识别的是数据包,而不是数据包的元组信息,无法识别网络流。因此,多处理器系统中,数据包需要被分配给特征相似的CPU进行处理,以降低CPU硬件高速缓存的刷新频率。
在多处理器系统中,每个处理器拥有单独的硬件高速缓存。当其中一个CPU修改了自己的硬件高速缓存,它必须通知其他CPU更新缓存,以保证缓存一致性。这样,CPU间的数据一致性问题需要解决,以避免数据乱序导致的重传问题。当Linux主机作为路由器时,进入系统的一个TCP包的不同分段如果被不同的CPU处理并向一个网卡转发,同步问题将变得复杂,这与一个CPU串行处理相比,效果更差。
RPS/RFS旨在解决上述问题,需要解决三个关键问题:数据包如何更高效地分配给CPU、TCP/IP包分段重组同步问题、以及如何确保数据流处理的一致性。
在Linux底层,数据结构隐藏了许多机密信息,包括面向对象的设计。以下是对关键数据结构的解析:
-网卡的硬件接收队列(netdev_rx_queue):存放解析结果,其中cpus数组记录参与报文分发处理的CPU数组,len成员表示cpus数组的长度。
- CPU负载表(rps_map):存放解析结果的容器,用于管理分配给CPU的数据包。
-设备流表(rps_dev_flow_table):由mask成员控制流表项的数量,通过配置文件指定。
-全局数据流表(rps_sock_flow_table):包含处理数据流的CPU信息,通过调用recvmsg、sendmsg等函数更新。
RPS工作流程如下:将数据包加入其他CPU的接收队列,这些CPU在软中断中执行process_backlog,接收队列中的所有数据包并调用__netif_receive_skb进行后续操作。
Linux通过配置文件指定参与报文分发处理的CPU列表,路径为/sys/class/net/(dev)/queues/rx-(n)/rps_cpus。内核根据配置生成用于处理报文的CPU列表,实现基于报文哈希值的负载均衡。RPS不关注处理该流中报文的应用程序所在CPU,但有NAPI接口的驱动中,上半部主要将设备加入到CPU私有数据待轮询列表,下半部从网卡缓冲区获取报文。
函数get_rps_cpu在netif_rcv_skb调用,获取目标CPU,将其加入到CPU私有数据对象的input_pkt_queue队列中。数据对象中的backlog成员类型为struct napi_struct,在enqueue_to_backlog函数中,将backlog加入待轮询列表,触发软中断处理,最后从input_pkt_queue队列中取出报文并上报协议栈。
RFS作为RPS的改进,在RPS的基础上,将同一流的数据包分发给同一个CPU核,但有可能导致处理该数据流的应用程序CPU核和实际执行处理的CPU核不同,导致缓存不命中问题。RFS通过指派应用程序所在CPU在内核态处理报文,增加缓存命中率,主要差别在于选择分发处理报文的目标CPU。
RFS实现通过设备流表和全局socket流表的记录比较,判断处理报文的CPU核是否一致。如果当前CPU表对应表项未设置或CPU核离线,使用期望CPU表对应表项映射的CPU核。如果当前和期望CPU核不同,RFS会使用设备流表和全局流表设置的CPU核。未设置时,使用RPS策略中的CPU流表或返回无效CPU_index。
配置方法:RPS和RFS在Linux kernel 2.6.35及以上版本中默认关闭,可通过/sys/class/net/(dev)/queues/rx-(n)/rps_cpus设置RPS接收队列和CPU列表,/sys/class/net/(dev)/queues/rx-(n)/rps_flow_cnt设置设备流表数量,/proc/sys/net/core/rps_sock_flow_entries设置全局数据流表数量。
Linux 中断( IRQ / softirq )基础:原理及内核实现
中断(IRQ),尤其是软中断(softirq)的广泛用途之一是网络数据包的接收与发送,但其应用场景并非单一。本文将全面整理中断(IRQ)与软中断(softirq)的基础知识,这些内容与网络数据包处理虽无直接联系,但整理本文旨在更深入地理解网络数据包处理机制。
什么是中断?
CPU通过时分复用处理多任务,其中包括硬件任务,如磁盘读写、键盘输入,以及软件任务,如网络数据包处理。CPU在任何时刻只能执行一个任务。当某个硬件或软件任务当前未被执行,但希望CPU立即处理时,会向CPU发送中断请求——希望CPU暂停手头工作,优先服务“我”。中断以事件形式通知CPU,因此常看到“在XX条件下会触发XX中断事件”的表述。
中断分为两类:
管理中断的设备:Advanced Programmable Interrupt Controller(APIC)。
硬中断的中断处理流程
中断随时发生,处理流程如下:
Maskable and non-maskable
Maskable interrupts在x64_64上可以通过sti/cli指令来屏蔽(关闭)和恢复:
在屏蔽期间,这种类型的中断不会触发新的中断事件。大部分IRQ都属于这种类型。例如,网卡的收发包硬件中断。
Non-maskable interrupts不可屏蔽,因此属于更高优先级的类型。
问题:执行速度与逻辑复杂性之间的矛盾
IRQ处理器的两个特点如下:
存在内在矛盾。
解决方式:中断的推迟处理(deferred interrupt handling)
传统解决方式是将中断处理分为两部分:
这种方式称为中断的推迟处理或延后处理。现在已是一个通用术语,涵盖各种推迟执行中断处理的方式。中断分为两部分处理:
在Linux中,有三种推迟中断(deferred interrupts):
具体细节将在后续介绍。
软中断与软中断子系统
软中断是内核子系统的一部分:
每个CPU上会初始化一个ksoftirqd内核线程,负责处理各种类型的softirq中断事件;
使用cgroup ls或ps-ef都能看到:
软中断事件的handler提前注册到softirq子系统,注册方式为open_softirq(softirq_id, handler)
例如,注册网卡收发包(RX/TX)软中断处理函数:
软中断占用了CPU的总开销:可以使用top查看,第三行倒数第二个指标是系统的软中断开销(si字段):
Linux内核源码分析学习地址:ke.qq.com/course/403254...
【文章福利】小编推荐自己的Linux内核源码分析交流群:【点击1095678385加入】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!
主处理
smpboot.c类似于事件驱动的循环,会调度ksoftirqd线程执行pending的软中断。ksoftirqd内部会进一步调用到__do_softirq,
避免软中断占用过多CPU
软中断的潜在影响:推迟执行的部分(如softirq)可能会占用较长时间,在这段时间内,用户空间线程只能等待。反映在top中,si占比。
不过softirq调度循环对此有所改进,通过budget机制来避免softirq占用过多CPU时间。
硬中断-软中断调用栈
softirq是一种推迟中断处理机制,将IRQ的大部分处理逻辑推迟在这里执行。有两条路径都会执行到softirq主处理逻辑__do_softirq():
1、CPU调度到ksoftirqd线程时,会执行到__do_softirq();
2、每次IRQ handler退出时:do_IRQ()->...
do_IRQ是内核中主要的IRQ处理方式。它执行结束时,会调用exiting_irq(),这会展开成irq_exit()。后者会检查是否pending有softirq,如果有,则唤醒:
进而会使CPU执行到__do_softirq。
软中断触发执行的步骤
总结,每个软中断会经过以下阶段:
以收包软中断为例,IRQ handler并不执行NAPI,只是触发它,在内部会执行到raiseNET_RX_SOFTIRQ;真正的执行在softirq,会调用网卡的poll()方法收包。IRQ handler中会调用napi_schedule(),然后启动NAPI poll()。
需要注意的是,虽然IRQ handler所做的工作很少,但处理这个包的softirq和IRQ在同一CPU上运行。这意味着,如果大量的包都放在同一个RX队列,虽然IRQ开销可能不多,但该CPU仍然会非常繁忙,都花费在softirq上。解决方式:RPS。它不会降低延迟,只是将包重新分配:RXQ->CPU。
三种推迟执行方式(softirq/tasklet/workqueue)
提到,Linux中的三种推迟中断执行方式:
其中:
前面已经看到,Linux在每个CPU上创建了一个ksoftirqd内核线程。
softirqs是在Linux内核编译时确定的,例如网络收包对应的NET_RX_SOFTIRQ软中断。因此是一种静态机制。如果想添加一种新softirq类型,需要修改并重新编译内核。
内部组织
内部由一个数组(或称为向量)管理,每个软中断号对应一个softirq handler。数组与注册:
在5.10中所有类型的softirq:
也就是在cat/proc/softirqs看到的哪些。
触发(唤醒)softirq
以收包软中断为例,IRQ handler并不执行NAPI,只是触发它,在内部会执行到raiseNET_RX_SOFTIRQ;真正的执行在softirq,会调用网卡的poll()方法收包。IRQ handler中会调用napi_schedule(),然后启动NAPI poll()。
如果对内核源码有一定了解,会发现softirq使用非常有限,原因之一是它是静态编译的,依赖内置的ksoftirqd线程来调度内置的9种softirq。如果想添加一种新功能,就得修改并重新编译内核,开发成本很高。
实际上,实现推迟执行的更常用方式是tasklet。它构建在softirq机制之上,具体来说就是使用了两种softirq:
换句话说,tasklet是在运行时(runtime)创建和初始化的softirq,
内核软中断子系统初始化了两个per-cpu变量:
tasklet再执行针对list的循环:
tasklet在内核中的使用非常广泛。不过,后面又出现了第三种方式:workqueue。
这也是一种推迟执行机制,与tasklet有些相似,但有显著不同。
使用场景
简而言之,workqueue子系统提供了一个接口,通过该接口可以创建内核线程来处理从其他地方enqueue过来的任务。这些内核线程称为worker threads,内置的per-cpu worker threads:
结构体
kworker线程调度workqueues,原理与ksoftirqd线程调度softirqs类似。然而,我们可以为workqueue创建新的线程,而softirq则不行。
参考资料引用链接
[1]
中断与中断处理:0xax.gitbooks.io/linux-...
作者:赵亚楠原文:arthurchiao.art/blog/li...来源:云原生实验室