linux 网卡 中断(linux查看网卡命令)
老铁们,大家好,相信还有很多朋友对于linux 网卡 中断和linux查看网卡命令的相关问题不太懂,没关系,今天就由我来为大家分享分享linux 网卡 中断以及linux查看网卡命令的问题,文章篇幅可能偏长,希望可以帮助到大家,下面一起来看看吧!
Linux系统中的进程调度介绍
操作系统要实现多进程,进程调度必不可少。
有人说,进程调度是操作系统中最为重要的一个部分。我觉得这种说法说得太绝对了一点,就像很多人动辄就说"某某函数比某某函数效率高XX倍"一样,脱离了实际环境,这些结论是比较片面的。
而进程调度究竟有多重要呢?首先,我们需要明确一点:进程调度是对TASK_RUNNING状态的进程进行调度(参见《linux进程状态浅析》)。如果进程不可执行(正在睡眠或其他),那么它跟进程调度没多大关系。
所以,如果你的系统负载非常低,盼星星盼月亮才出现一个可执行状态的进程。那么进程调度也就不会太重要。哪个进程可执行,就让它执行去,没有什么需要多考虑的。
反之,如果系统负载非常高,时时刻刻都有N多个进程处于可执行状态,等待被调度运行。那么进程调度程序为了协调这N个进程的执行,必定得做很多工作。协调得不好,系统的性能就会大打折扣。这个时候,进程调度就是非常重要的。
尽管我们平常接触的很多计算机(如桌面系统、网络服务器、等)负载都比较低,但是linux作为一个通用操作系统,不能假设系统负载低,必须为应付高负载下的进程调度做精心的设计。
当然,这些设计对于低负载(且没有什么实时性要求)的环境,没多大用。极端情况下,如果CPU的负载始终保持0或1(永远都只有一个进程或没有进程需要在CPU上运行),那么这些设计基本上都是徒劳的。
优先级
现在的操作系统为了协调多个进程的“同时”运行,最基本的手段就是给进程定义优先级。定义了进程的优先级,如果有多个进程同时处于可执行状态,那么谁优先级高谁就去执行,没有什么好纠结的了。
那么,进程的优先级该如何确定呢?有两种方式:由用户程序指定、由内核的调度程序动态调整。(下面会说到)
linux内核将进程分成两个级别:普通进程和实时进程。实时进程的优先级都高于普通进程,除此之外,它们的调度策略也有所不同。
实时进程的调度
实时,原本的涵义是“给定的操作一定要在确定的时间内完成”。重点并不在于操作一定要处理得多快,而是时间要可控(在最坏情况下也不能突破给定的时间)。
这样的“实时”称为“硬实时”,多用于很精密的系统之中(比如什么火箭、导弹之类的)。一般来说,硬实时的系统是相对比较专用的。
像linux这样的通用操作系统显然没法满足这样的要求,中断处理、虚拟内存、等机制的存在给处理时间带来了很大的不确定性。硬件的cache、磁盘寻道、总线争用、也会带来不确定性。
比如考虑“i++;”这么一句C代码。绝大多数情况下,它执行得很快。但是极端情况下还是有这样的可能:
1、i的内存空间未分配,CPU触发缺页异常。而linux在缺页异常的处理代码中试图分配内存时,又可能由于系统内存紧缺而分配失败,导致进程进入睡眠;
2、代码执行过程中硬件产生中断,linux进入中断处理程序而搁置当前进程。而中断处理程序的处理过程中又可能发生新的硬件中断,中断永远嵌套不止……;
等等……
而像linux这样号称实现了“实时”的通用操作系统,其实只是实现了“软实时”,即尽可能地满足进程的实时需求。
如果一个进程有实时需求(它是一个实时进程),则只要它是可执行状态的,内核就一直让它执行,以尽可能地满足它对CPU的需要,直到它完成所需要做的事情,然后睡眠或退出(变为非可执行状态)。
而如果有多个实时进程都处于可执行状态,则内核会先满足优先级最高的实时进程对CPU的需要,直到它变为非可执行状态。
于是,只要高优先级的实时进程一直处于可执行状态,低优先级的实时进程就一直不能得到CPU;只要一直有实时进程处于可执行状态,普通进程就一直不能得到CPU。
那么,如果多个相同优先级的实时进程都处于可执行状态呢?这时就有两种调度策略可供选择:
1、SCHED_FIFO:先进先出。直到先被执行的进程变为非可执行状态,后来的进程才被调度执行。在这种策略下,先来的进程可以执行sched_yield系统调用,自愿放弃CPU,以让权给后来的进程;
2、SCHED_RR:轮转调度。内核为实时进程分配时间片,在时间片用完时,让下一个进程使用CPU;
强调一下,这两种调度策略以及sched_yield系统调用都仅仅针对于相同优先级的多个实时进程同时处于可执行状态的情况。
在linux下,用户程序可以通过sched_setscheduler系统调用来设置进程的调度策略以及相关调度参数;sched_setparam系统调用则只用于设置调度参数。这两个系统调用要求用户进程具有设置进程优先级的能力(CAP_SYS_NICE,一般来说需要root权限)(参阅capability相关的文章)。
通过将进程的策略设为SCHED_FIFO或SCHED_RR,使得进程变为实时进程。而进程的优先级则是通过以上两个系统调用在设置调度参数时指定的。
对于实时进程,内核不会试图调整其优先级。因为进程实时与否?有多实时?这些问题都是跟用户程序的应用场景相关,只有用户能够回答,内核不能臆断。
综上所述,实时进程的调度是非常简单的。进程的优先级和调度策略都由用户定死了,内核只需要总是选择优先级最高的实时进程来调度执行即可。唯一稍微麻烦一点的只是在选择具有相同优先级的实时进程时,要考虑两种调度策略。
普通进程的调度
实时进程调度的中心思想是,让处于可执行状态的最高优先级的实时进程尽可能地占有CPU,因为它有实时需求;而普通进程则被认为是没有实时需求的进程,于是调度程序力图让各个处于可执行状态的普通进程和平共处地分享CPU,从而让用户觉得这些进程是同时运行的。
与实时进程相比,普通进程的调度要复杂得多。内核需要考虑两件麻烦事:
一、动态调整进程的优先级
按进程的行为特征,可以将进程分为“交互式进程”和“批处理进程”:
交互式进程(如桌面程序、服务器、等)主要的任务是与外界交互。这样的进程应该具有较高的优先级,它们总是睡眠等待外界的输入。而在输入到来,内核将其唤醒时,它们又应该很快被调度执行,以做出响应。比如一个桌面程序,如果鼠标点击后半秒种还没反应,用户就会感觉系统“卡”了;
批处理进程(如编译程序)主要的任务是做持续的运算,因而它们会持续处于可执行状态。这样的进程一般不需要高优先级,比如编译程序多运行了几秒种,用户多半不会太在意;
如果用户能够明确知道进程应该有怎样的优先级,可以通过nice、setpriority系统调用来对优先级进行设置。(如果要提高进程的优先级,要求用户进程具有CAP_SYS_NICE能力。)
然而应用程序未必就像桌面程序、编译程序这样典型。程序的行为可能五花八门,可能一会儿像交互式进程,一会儿又像批处理进程。以致于用户难以给它设置一个合适的优先级。
再者,即使用户明确知道一个进程是交互式还是批处理,也多半碍于权限或因为偷懒而不去设置进程的优先级。(你又是否为某个程序设置过优先级呢?)
于是,最终,区分交互式进程和批处理进程的重任就落到了内核的调度程序上。
调度程序关注进程近一段时间内的表现(主要是检查其睡眠时间和运行时间),根据一些经验性的公式,判断它现在是交互式的还是批处理的?程度如何?最后决定给它的优先级做一定的调整。
进程的优先级被动态调整后,就出现了两个优先级:
1、用户程序设置的优先级(如果未设置,则使用默认值),称为静态优先级。这是进程优先级的基准,在进程执行的过程中往往是不改变的;
2、优先级动态调整后,实际生效的优先级。这个值是可能时时刻刻都在变化的;
二、调度的公平性
在支持多进程的系统中,理想情况下,各个进程应该是根据其优先级公平地占有CPU。而不会出现“谁运气好谁占得多”这样的不可控的情况。
linux实现公平调度基本上是两种思路:
1、给处于可执行状态的进程分配时间片(按照优先级),用完时间片的进程被放到“过期队列”中。等可执行状态的进程都过期了,再重新分配时间片;
2、动态调整进程的优先级。随着进程在CPU上运行,其优先级被不断调低,以便其他优先级较低的进程得到运行机会;
后一种方式有更小的调度粒度,并且将“公平性”与“动态调整优先级”两件事情合而为一,大大简化了内核调度程序的代码。因此,这种方式也成为内核调度程序的新宠。
强调一下,以上两点都是仅针对普通进程的。而对于实时进程,内核既不能自作多情地去动态调整优先级,也没有什么公平性可言。
普通进程具体的调度算法非常复杂,并且随linux内核版本的演变也在不断更替(不仅仅是简单的调整),所以本文就不继续深入了。
调度程序的效率
“优先级”明确了哪个进程应该被调度执行,而调度程序还必须要关心效率问题。调度程序跟内核中的很多过程一样会频繁被执行,如果效率不济就会浪费很多CPU时间,导致系统性能下降。
在linux 2.4时,可执行状态的进程被挂在一个链表中。每次调度,调度程序需要扫描整个链表,以找出最优的那个进程来运行。复杂度为O(n);
在linux 2.6早期,可执行状态的进程被挂在N(N=140)个链表中,每一个链表代表一个优先级,系统中支持多少个优先级就有多少个链表。每次调度,调度程序只需要从第一个不为空的链表中取出位于链表头的进程即可。这样就大大提高了调度程序的效率,复杂度为O(1);
在linux 2.6近期的版本中,可执行状态的进程按照优先级顺序被挂在一个红黑树(可以想象成平衡二叉树)中。每次调度,调度程序需要从树中找出优先级最高的进程。复杂度为O(logN)。
那么,为什么从linux 2.6早期到近期linux 2.6版本,调度程序选择进程时的复杂度反而增加了呢?
这是因为,与此同时,调度程序对公平性的实现从上面提到的第一种思路改变为第二种思路(通过动态调整优先级实现)。而O(1)的算法是基于一组数目不大的链表来实现的,按我的理解,这使得优先级的取值范围很小(区分度很低),不能满足公平性的需求。而使用红黑树则对优先级的取值没有限制(可以用32位、64位、或更多位来表示优先级的值),并且O(logN)的复杂度也还是很高效的。
调度触发的时机
调度的触发主要有如下几种情况:
1、当前进程(正在CPU上运行的进程)状态变为非可执行状态。
进程执行系统调用主动变为非可执行状态。比如执行nanosleep进入睡眠、执行exit退出、等等;
进程请求的资源得不到满足而被迫进入睡眠状态。比如执行read系统调用时,磁盘高速缓存里没有所需要的数据,从而睡眠等待磁盘IO;
进程响应信号而变为非可执行状态。比如响应SIGSTOP进入暂停状态、响应SIGKILL退出、等等;
2、抢占。进程运行时,非预期地被剥夺CPU的使用权。这又分两种情况:进程用完了时间片、或出现了优先级更高的进程。
优先级更高的进程受正在CPU上运行的进程的影响而被唤醒。如发送信号主动唤醒,或因为释放互斥对象(如释放锁)而被唤醒;
内核在响应时钟中断的过程中,发现当前进程的时间片用完;
内核在响应中断的过程中,发现优先级更高的进程所等待的外部资源的变为可用,从而将其唤醒。比如CPU收到网卡中断,内核处理该中断,发现某个socket可读,于是唤醒正在等待读这个socket的进程;再比如内核在处理时钟中断的过程中,触发了定时器,从而唤醒对应的正在nanosleep系统调用中睡眠的进程。
所有任务都采用linux分时调度策略时:
1,创建任务指定采用分时调度策略,并指定优先级nice值(-20~19)。
2,将根据每个任务的nice值确定在cpu上的执行时间(counter)。
3,如果没有等待资源,则将该任务加入到就绪队列中。
4,调度程序遍历就绪队列中的任务,通过对每个任务动态优先级的计算权值(counter+20-nice)结果,选择计算结果最大的一个去运行,当这个时间片用完后(counter减至0)或者主动放弃cpu时,该任务将被放在就绪队列末尾(时间片用完)或等待队列(因等待资源而放弃cpu)中。
5,此时调度程序重复上面计算过程,转到第4步。
6,当调度程序发现所有就绪任务计算所得的权值都为不大于0时,重复第2步。
所有任务都采用FIFO时:
1,创建进程时指定采用FIFO,并设置实时优先级rt_priority(1-99)。
2,如果没有等待资源,则将该任务加入到就绪队列中。
3,调度程序遍历就绪队列,根据实时优先级计算调度权值(1000+rt_priority),选择权值最高的任务使用cpu,该FIFO任务将一直占有cpu直到有优先级更高的任务就绪(即使优先级相同也不行)或者主动放弃(等待资源)。
4,调度程序发现有优先级更高的任务到达(高优先级任务可能被中断或定时器任务唤醒,再或被当前运行的任务唤醒,等等),则调度程序立即在当前任务堆栈中保存当前cpu寄存器的所有数据,重新从高优先级任务的堆栈中加载寄存器数据到cpu,此时高优先级的任务开始运行。重复第3步。
5,如果当前任务因等待资源而主动放弃cpu使用权,则该任务将从就绪队列中删除,加入等待队列,此时重复第3步。
所有任务都采用RR调度策略时:
1,创建任务时指定调度参数为RR,并设置任务的实时优先级和nice值(nice值将会转换为该任务的时间片的长度)。
2,如果没有等待资源,则将该任务加入到就绪队列中。
3,调度程序遍历就绪队列,根据实时优先级计算调度权值(1000+rt_priority),选择权值最高的任务使用cpu。
4,如果就绪队列中的RR任务时间片为0,则会根据nice值设置该任务的时间片,同时将该任务放入就绪队列的末尾。重复步骤3。
5,当前任务由于等待资源而主动退出cpu,则其加入等待队列中。重复步骤3。
系统中既有分时调度,又有时间片轮转调度和先进先出调度:
1,RR调度和FIFO调度的进程属于实时进程,以分时调度的进程是非实时进程。
2,当实时进程准备就绪后,如果当前cpu正在运行非实时进程,则实时进程立即抢占非实时进程。
3,RR进程和FIFO进程都采用实时优先级做为调度的权值标准,RR是FIFO的一个延伸。FIFO时,如果两个进程的优先级一样,则这两个优先级一样的进程具体执行哪一个是由其在队列中的未知决定的,这样导致一些不公正性(优先级是一样的,为什么要让你一直运行?),如果将两个优先级一样的任务的调度策略都设为RR,则保证了这两个任务可以循环执行,保证了公平。
Ingo Molnar-实时补丁
为了能并入主流内核,Ingo Molnar的实时补丁也采用了非常灵活的策略,它支持四种抢占模式:
1.No Forced Preemption(Server),这种模式等同于没有使能抢占选项的标准内核,主要适用于科学计算等服务器环境。
2.Voluntary Kernel Preemption(Desktop),这种模式使能了自愿抢占,但仍然失效抢占内核选项,它通过增加抢占点缩减了抢占延迟,因此适用于一些需要较好的响应性的环境,如桌面环境,当然这种好的响应性是以牺牲一些吞吐率为代价的。
3.Preemptible Kernel(Low-Latency Desktop),这种模式既包含了自愿抢占,又使能了可抢占内核选项,因此有很好的响应延迟,实际上在一定程度上已经达到了软实时性。它主要适用于桌面和一些嵌入式系统,但是吞吐率比模式2更低。
4.Complete Preemption(Real-Time),这种模式使能了所有实时功能,因此完全能够满足软实时需求,它适用于延迟要求为100微秒或稍低的实时系统。
实现实时是以牺牲系统的吞吐率为代价的,因此实时性越好,系统吞吐率就越低。
关于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】网卡overruns报错问题原因及解决方案
环境信息:
cpu:40c
操作系统:ceontos6.7
部署服务:DataNode、NodeManager、Impala服务。
一、前言:
之前发生过某台节点网卡报错,影响结果 presto任务失败、HDFS读取变慢、Yarn任务执行变慢。
于是后续对net.if.total.errors这个指标统一加上了监控,过了一段时间后,在别的节点也收到了类似的报警。
于是想到还是之前的错误,于是让OP同学帮忙重新切换了网卡,切换网卡后一段时间确实没有收到告警了。但是过段时间(4-5小时)又收到了新告警。
于是将运行的NodeManager、Impala的服务停止到,只保留了DataNode服务。
结果网卡报错的情况依旧没有缓解。仍然收到大量的告警。通过观察监控,发现该节点的数据写入的平均时间较别的节点时间较长。
二、调研:查看网卡信息
在使用ifconfig命令查看网卡信息时,对于收发包的统计里有dropped与overruns两个字段,看上去都是丢包,但它们有什么区别呢?
ifconfig-a
查看结果:具体解释如下:
dropped,表示这个数据包已经进入到网卡的接收缓存fifo队列,并且开始被系统中断处理准备进行数据包拷贝(从网卡缓存fifo队列拷贝到系统内存),但由于此时的系统原因(比如内存不够等)导致这个数据包被丢掉,即这个数据包被Linux系统丢掉。
overruns,表示这个数据包还没有被进入到网卡的接收缓存fifo队列就被丢掉,因此此时网卡的fifo是满的。为什么fifo会是满的?因为系统繁忙,来不及响应网卡中断,导致网卡里的数据包没有及时的拷贝到系统内存,fifo是满的就导致后面的数据包进不来,即这个数据包被网卡硬件丢掉。
所以,个人觉得遇到overruns非0,需要检测cpu负载与cpu中断情况。
查看cpu软中断
下图选中的为优化前和优化后的对比。
通过查看Cpu idle,发现会有个别的cpu被打满的现象观察软中断也相较别的节点较高。于是决定对网卡软中断绑定优化。
三、多队列网卡
多队列网卡顾名思义就是由原来的单网卡单队列变成了现在的单网卡多队列。多队列网卡是一种技术,最初是用来解决网络IO QoS(quality of service)问题的,后来随着网络IO的带宽的不断提升,单核CPU不能完全处满足网卡的需求,体现最为明显的就是单核CPU处理不了网卡大量的数据包请求(软中断)而造成大量丢包,
其实当网卡收到数据包时会产生中断,通知内核有新数据包,然后内核调用中断处理程序进行响应,把数据包从网卡缓存拷贝到内存,因为网卡缓存大小有限,如果不及时拷出数据,后续数据包将会因为缓存溢出被丢弃,因此这一工作需要立即完成。
剩下的处理和操作数据包的工作就会交给软中断,高负载的网卡是软中断产生的大户,很容易形成瓶颈。但通过多队列网卡驱动的支持,将各个队列通过中断绑定到不同的CPU核上,以满足网卡的需求,这就是多队列网卡的应用。
网卡软中断不平衡:
集中在一个CPU核心上(mpstat查看%soft集中,通常是cpu0)。
网卡的硬件中断队列不够,< CPU核心数,无法一对一绑定,导致部分CPU核心%soft较少,CPU使用不均衡。
所以如果网络流量大的时候,就需要将软中断均匀的分散到各个核上,避免单个CPU core成为瓶颈。
四、SMP IRQ affinity
Linux 2.4内核之后引入了将特定中断绑定到指定的CPU的技术,称为SMP IRQ affinity.
原理:
当一个硬件(如磁盘控制器或者以太网卡),需要打断CPU的工作时,它就触发一个中断.该中断通知CPU发生了某些事情并且CPU应该放下当前的工作去处理这个事情.为了防止多个设置发送相同的中断, Linux设计了一套中断请求系统,使得计算机系统中的每个设备被分配了各自的中断号,以确保它的中断请求的唯一性.
从2.4内核开始, Linux改进了分配特定中断到指定的处理器(或处理器组)的功能.这被称为SMP IRQ affinity,它可以控制系统如何响应各种硬件事件.允许你限制或者重新分配服务器的工作负载,从而让服务器更有效的工作.以网卡中断为例,在没有设置SMP IRQ affinity时,所有网卡中断都关联到CPU0,这导致了CPU0负载过高,而无法有效快速的处理网络数据包,导致了瓶颈。
通过SMP IRQ affinity,把网卡多个中断分配到多个CPU上,可以分散CPU压力,提高数据处理速度。
使用前提:
需要多CPU的系统
需要大于等于2.4的Linux内核
五、解决方法:脚本内容:#!/bin/bash## Copyright(c) 2014, Intel Corporation## Redistribution and use in source and binary forms, with or without# modification, are permitted provided that the following conditions are met:##* Redistributions of source code must retain the above copyright notice,# this list of conditions and the following disclaimer.#* Redistributions in binary form must reproduce the above copyright# notice, this list of conditions and the following disclaimer in the# documentation and/or other materials provided with the distribution.#* Neither the name of Intel Corporation nor the names of its contributors# may be used to endorse or promote products derived from this software# without specific prior written permission.## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS"AS IS"# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL# DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,# OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.## Affinitize interrupts to cores## typical usage is(as root):# set_irq_affinity-x local eth1<eth2><eth3>## to get help:# set_irq_affinityusage(){echoecho"Usage:$0 [-x|-X]{all|local|remote|one|custom} [ethX]<[ethY]>"echo"options:-x Configure XPS as well as smp_affinity"echo"options:-X Disable XPS but set smp_affinity"echo"options:{remote|one} can be followed by a specific node number"echo"Ex:$0 local eth0"echo"Ex:$0 remote 1 eth0"echo"Ex:$0 custom eth0 eth1"echo"Ex:$0 0-7,16-23 eth0"echoexit 1}usageX(){echo"options-x and-X cannot both be specified, pick one"exit 1}if ["$1"=="-x" ]; thenXPS_ENA=1shiftfiif ["$1"=="-X" ]; thenif [-n"$XPS_ENA" ]; thenusageXfiXPS_DIS=2shiftfiif ["$1"==-x ]; thenusageXfiif [-n"$XPS_ENA" ]&& [-n"$XPS_DIS" ]; thenusageXfiif [-z"$XPS_ENA" ]; thenXPS_ENA=$XPS_DISfinum='^[0-9]+$'# VarsAFF=$1shiftcase"$AFF" inremote) [[$1=~$num ]]&& rnode=$1&& shift;;one)[[$1=~$num ]]&& cnt=$1&& shift;;all);;local);;custom);;[0-9]*);;-h|--help)usage;;"") usage;;*)IFACES=$AFF&& AFF=all;;# Backwards compat modeesac# append the interfaces listed to the string with spaceswhile ["$#"-ne"0" ]; doIFACES+="$1"shiftdone# for now the user must specify interfacesif [-z"$IFACES" ]; thenusageexit 1fi# support functionsset_affinity(){VEC=$coreif [$VEC-ge 32 ]thenMASK_FILL=""MASK_ZERO="00000000"let"IDX=$VEC/ 32"for((i=1; i<=$IDX;i++))doMASK_FILL="${MASK_FILL},${MASK_ZERO}"donelet"VEC-= 32*$IDX"MASK_TMP=$((1<<$VEC))MASK=$(printf"%X%s"$MASK_TMP$MASK_FILL)elseMASK_TMP=$((1<<$VEC))MASK=$(printf"%X"$MASK_TMP)fiprintf"%s"$MASK>/proc/irq/$IRQ/smp_affinityprintf"%s%d%s->/proc/irq/$IRQ/smp_affinity\n"$IFACE$core$MASKcase"$XPS_ENA" in1)printf"%s%d%s->/sys/class/net/%s/queues/tx-%d/xps_cpus\n"$IFACE$core$MASK$IFACE$((n-1))printf"%s"$MASK>/sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus;;2)MASK=0printf"%s%d%s->/sys/class/net/%s/queues/tx-%d/xps_cpus\n"$IFACE$core$MASK$IFACE$((n-1))printf"%s"$MASK>/sys/class/net/$IFACE/queues/tx-$((n-1))/xps_cpus;;*)esac}# Allow usage of, or-#parse_range(){RANGE=${@//,/}RANGE=${RANGE//-/..}LIST=""for r in$RANGE; do# eval lets us use vars in{#..#} range[[$r=~'..' ]]&& r="$(eval echo{$r})"LIST+="$r"doneecho$LIST}# Affinitize interrupts#setaff(){CORES=$(parse_range$CORES)ncores=$(echo$CORES| wc-w)n=1# this script only supports interrupt vectors in pairs,# modification would be required to support a single Tx or Rx queue# per interrupt vectorqueues="${IFACE}-.*TxRx"irqs=$(grep"$queues"/proc/interrupts| cut-f1-d:)[-z"$irqs" ]&& irqs=$(grep$IFACE/proc/interrupts| cut-f1-d:)[-z"$irqs" ]&& irqs=$(for i in `ls-Ux/sys/class/net/$IFACE/device/msi_irqs`;\ do grep"$i:.*TxRx"/proc/interrupts| grep-v fdir| cut-f 1-d:;\ done)[-z"$irqs" ]&& echo"Error: Could not find interrupts for$IFACE"echo"IFACE CORE MASK-> FILE"echo"======================="for IRQ in$irqs; do["$n"-gt"$ncores" ]&& n=1j=1# much faster than calling cut for eachfor i in$CORES; do[$((j++))-ge$n ]&& breakdonecore=$iset_affinity((n++))done}# now the actual useful bits of code# these next 2 lines would allow script to auto-determine interfaces#[-z"$IFACES" ]&& IFACES=$(ls/sys/class/net)#[-z"$IFACES" ]&& echo"Error: No interfaces up"&& exit 1# echo IFACES is$IFACESCORES=$(</sys/devices/system/cpu/online)["$CORES" ]|| CORES=$(grep ^proc/proc/cpuinfo| cut-f2-d:)# Core list for each node from sysfsnode_dir=/sys/devices/system/nodefor i in$(ls-d$node_dir/node*); doi=${i/*node/}corelist[$i]=$(<$node_dir/node${i}/cpulist)donefor IFACE in$IFACES; do# echo$IFACE being modifieddev_dir=/sys/class/net/$IFACE/device[-e$dev_dir/numa_node ]&& node=$(<$dev_dir/numa_node)["$node" ]&& ["$node"-gt 0 ]|| node=0case"$AFF" inlocal)CORES=${corelist[$node]};;remote)["$rnode" ]||{ [$node-eq 0 ]&& rnode=1|| rnode=0;}CORES=${corelist[$rnode]};;one)[-n"$cnt" ]|| cnt=0CORES=$cnt;;all)CORES=$CORES;;custom)echo-n"Input cores for$IFACE(ex. 0-7,15-23):"read CORES;;[0-9]*)CORES=$AFF;;*)usageexit 1;;esac# call the worker functionsetaffdone# check for irqbalance runningIRQBALANCE_ON=`ps ax| grep-v grep| grep-q irqbalance; echo$?`if ["$IRQBALANCE_ON"=="0" ]; thenecho" WARNING: irqbalance is running and will"echo"likely override this script's affinitization."echo"Please stop the irqbalance service and/or execute"echo"'killall irqbalance'"fi执行脚本sh set_irq.sh local eth0原文: