NAPI(New API)是Linux内核针对网络数据传输做出的一个优化措施,其目的是在高负载的大数据传输时,网络驱动收到硬件中断后,通过poll(轮询)方式将传输过来的数据包统一处理, 在poll时通过禁止网络设备中断以减少硬件中断数量(Interrupt Mitigation
),从而实现更高的数据传输速率。
基于NAPI接口, 一般的网络传输(接收)有如下几个步骤:
- 网络设备驱动加载与初始化(配置IP等)
- 数据包从网络侧发送到网卡(
Network Interface Controller
, NIC) - 通过DMA(Direct Memory Access),将数据从网卡拷贝到内存的环形缓冲区(ring buffer)
- 数据从网卡拷贝到内存后, NIC产生硬件中断告知内核有新的数据包达到
- 内核收到中断后, 调用相应中断处理函数, 此时就会调用NAPI接口
__napi_schedule
开启poll线程(实际是触发一个软中断NET_RX_SOFTIRQ
)(常规数据传输, 一般在处理NIC的中断时调用netif_rx_action
处理网卡队列的数据) ksoftirqd
(每个CPU上都会启动一个软中断处理线程)收到软中断后被唤醒, 然后执行函数net_rx_action
, 这个函数负责调用NAPI的poll
接口来获取内存环形缓冲区的数据包- 解除网卡
ring buffer
中的DMA内存映射(unmapped), 数据由CPU负责处理,netif_receive_skb
传递回内核协议栈 - 如果内核支持数据包定向分发(
packet steering
)或者NIC本身支持多个接收队列的话, 从网卡过来的数据会在不同的CPU之间进行均衡, 这样可以获得更高的网络速率 - 网络协议栈处理数据包,并将其发送到对应应用的
socket
接收缓冲区