正如您从上一篇文章中看到的那样,NET_TX_SOFTIRQ 软中断已向其注册了函数 net_tx_action。这意味着有一个内核线程在执行 net_tx_action。该线程偶尔会暂停并 raise_softirq_irqoff 恢复它。让我们看看 net_tx_action 做了什么,以便我们了解内核如何处理传输请求。
写kthread
的时候偶尔会停顿。当 akthread
暂停时,为什么?
kthread 如何知道要执行的工作?它会轮询队列吗?
正如您从上一篇文章中看到的那样,NET_TX_SOFTIRQ 软中断已向其注册了函数 net_tx_action。这意味着有一个内核线程在执行 net_tx_action。该线程偶尔会暂停并 raise_softirq_irqoff 恢复它。让我们看看 net_tx_action 做了什么,以便我们了解内核如何处理传输请求。
写kthread
的时候偶尔会停顿。当 akthread
暂停时,为什么?
kthread 如何知道要执行的工作?它会轮询队列吗?
我认为关于暂停线程的说法更像是一种修辞格。在这种情况下,它不是kthread
暂停,线程工作得很好。
与 softirq 相关的工作主体正在__do_softirq()
运行。
有许多软中断类型,每个软中断类型由位掩码中的位表示。每当有针对特定类型的软中断的工作时,相应的位就会在位掩码中产生。__do_softirq()
从最低有效位开始逐位处理此位掩码,并为每个设置了该位的软中断类型执行工作。因此,softirq 类型按优先级顺序处理,位 0 表示最高优先级。事实上,如果您查看代码,您会看到位掩码已保存(复制),然后在处理开始之前清除,并且处理的是副本。
NET_TX_SOFTIRQ
每次将新的 skb 提交到内核网络堆栈以发送数据时,都会提高该位。这导致__do_softirq()
需要net_tx_action()
传出数据。如果没有要发送的数据,则不会提高该位。本质上,这就是导致内核 softirq 线程“暂停”的原因,这只是一种外行的说法,即它没有工作,所以net_tx_action()
不被调用。一旦有更多数据,当数据提交到内核网络堆栈时,该位就会再次升高。__do_softirq()
看到并net_tx_action()
再次打电话。
每个 CPU 上都有一个 softirq 线程。当至少有一个挂起的 softirq 类型时运行一个线程。线程在softirq_threads
结构中定义并在spawn_softirqd()
功能中启动。