New API是Linux内核接收网络中的数据包所调用的一个接口,能够有效减少Linux内核接收数据包时的损耗。
实现网络驱动最简单的办法是,每次收到一个包,就向内核提出一个中断请求。但是,当网络中包的数量非常多时,这种方式会给Linux内核带来极大的损耗,使得内核没有时间运行其他进程。
池化(Polling)可以解决上述问题。池化指的是Linux内核周期性地检查是否有需要处理的包,这种方式完全不需要Linux内核处理中断请求。但是,Linux内核检查包的周期太长或太短都不好。如果太长,那么缓存的包可能来不及处理就因为空间已满而被丢弃,造成丢包的问题。如果太短,则check的次数太多,很占用内核资源。
Linux内核采用了一种折中的机制:平时使用中断的方式接收包,当包的数量足够多,超过一个阈值时,转换到池化模式。
调用NAPI(New API)的网络驱动会这样工作:
- 接收包时不允许中断;
- 网络驱动向内核提供一个池化方法,内核调用之后可以获取所有待处理的包;
- 当被允许时,内核调用该方法,尝试立即处理这些包。
NAPI有很多优点:
- Linux内核去除了处理中断带来的负载;
- 接收的数据包更加有序;
- 当内核无法处理所有包时,丢弃的包在网络驱动内部直接被后来的包所覆盖,内核无需做任何事。在传统的处理方式下,内核需要一个个载入数据包并处理,可能导致内核中的虚拟内存被过度使用,导致颠簸 (Thrashing)。