首页 > 解决方案 > 内核线程执行更多通信工作时出现不希望的延迟

问题描述

我们开发了一个内核模块,其行为基本上类似于有线通信流量(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。

标签: clinux-kernelschedulingpreemption

解决方案


推荐阅读