我们开发了一个内核模块,其行为基本上类似于有线通信流量(eth,...) - WiFi 网桥。它定期将传入的有线数据转发到 WiFi,反之亦然。该系统由运行相同内核模块的两个设备组成。在某些情况下,我们会遇到不希望的延迟。
该模块启动一个内核线程,该线程基本上执行:
while(1) {
schedule()
do_bridge_work()
usleep_range(200, 500)
}
在正常操作期间,top
命令显示:
CPU: 0% usr 19% sys 0% nic 60% idle 0% io 0% irq 19% sirq
Load average: 1.03 1.06 1.01 1/54 491
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
491 2 root DW 0 0% 29% [bridge_thread]
3 2 root SW 0 0% 10% [ksoftirqd/0]
当诊断被激活时,线程还会发送额外的诊断有线 eth 数据包。在这种模式下,从一侧到另一侧的设备 ping 从 5-6 毫秒到 45-900 毫秒。 top
然后显示:
CPU: 0% usr 25% sys 0% nic 50% idle 0% io 0% irq 24% sirq
Load average: 1.06 1.07 1.01 1/54 491
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
491 2 root DW 0 0% 35% [bridge_thread]
3 2 root SW 0 0% 14% [ksoftirqd/0]
schedule()
如果在 之前插入一个额外的usleep_range()
,或者如果增加睡眠时间,它会大大减少延迟。我想我已经缩小范围得出结论,RX softirq 没有获得处理传入流量(NET_RX_SOFTIRQ
)所需的调度时间。这是基于传输数据包的时间非常好这一事实。
我的问题是:
1:为什么ping时间会因为更多的工作而增加do_bridge_work()
(更多的处理和额外的数据包传输)。是不是NET_RX_SOFTIRQ
饿死了?
2:为什么schedule()
插入additional时ping时间会减少,或者增加sleep时间?这是否意味着 200-500 us 不足以处理所有挂起的软中断工作,并且较低的软中断被饿死了?添加额外的效果是否与schedule()
通过增加睡眠时间让其他人做更多的工作相同?
内核版本为 4.1.38,配置为 NO_HZ,PREEMPT = y。