我们已经开发了一个内核模块,其功能基本上类似于有线通信流量(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()
或增加睡眠时间时ping时间会减少?这是否意味着200-500 us不足以处理所有待处理的softirq,而较低的softirq却挨饿了?添加其他schedule()
的效果是否与其他方法一样,通过增加睡眠时间来完成更多工作?
内核版本为4.1.38,配置为NO_HZ,PREEMPT = y。