谁做Napi调度

who does Napi scheduling

我在阅读网络驱动程序中的 NAPI 调度时有疑问。

通常,整个网络处理代码都在软中断上下文中运行。并且使用 NAPI 轮询机制,驱动程序将在中断到达后轮询数据包。

那么,如果 NAPI 代码也在 softirq 上下文中运行,那么如何安排它呢? (因为,无法安排中断上下文代码)。

以及网络驱动程序中工作队列的用途是什么。

NAPI 意义上的调度只是意味着将其标记为需要 运行。换句话说,您只需让函数调用说 "schedule me to run in the NAPI softirq"。这会导致您的驱动程序的轮询功能被添加到 "need-to-be-polled" 设备列表中,并且它 也会 导致 NAPI softirq 被激活 "on the way out."

所以它通常以这种方式工作。您的驱动程序将您的设备配置为告诉它在将来某个时间点中断某些数据包(最好是多个数据包以便分摊开销)准备好进行处理。同时,内核调度普通用户-space 进程...

当您的设备中断时:

  • 如果尚未处于内核模式,则中断会导致过渡到内核模式
  • linux 中断处理代码找到您的驱动程序的中断处理程序并调用它。
  • 您的中断处理程序调用 napi_schedule(将您的轮询函数放在列表中并触发软中断。
  • 你的中断处理程序returns.
  • 就在返回用户模式之前(或者 CPU 在中断之前所做的任何事情),中断处理代码发现网络软中断需要 运行 并激活它。
  • softirq 调用您的轮询函数来处理传入的数据包,直到您没有更多的数据包或直到 NAPI "budget" 耗尽。 (在后一种情况下,[我认为] ksoftirqd 线程稍后会重新调用 softirq。)
  • 您的驱动程序只有在处理完所有准备处理的数据包后才会在您的设备上重新启用中断。

根据我的经验,工作队列通常仅用于某些需要在可调度上下文中完成的长时间操作(即在等待某事完成时可以阻塞 [睡眠] 的真实任务上下文) .

例如在intel ixgbe驱动中,如果驱动检测到网卡需要reset,就会触发work-queue entry重新初始化网卡。有些操作需要相对较长的休眠时间,如果可以让其他任务执行 运行,则您不想将处理器占用在软中断上下文中。也可能有其他原因——例如,您需要分配大量内存,这可能需要在任务上下文中进行分配调用。