流量采集 中断活锁与 NAPI 技术
针对中断活锁,Jeffrey C.Mogul 在 USENIX 1996 会议上发表的一篇论文专门提出了相应的解决方案,该方案成为时下流行的 NAPI 技术的前身。为了解决中断活锁问题,必须降低网卡产生中断的频率。一种行之有效的降低中断频率方法是采用轮询技术。轮询在重负载时效率很高,在轻负载时则会增加延迟。中断在轻负载时可减小响应延迟,在重负载时将会导致中断活锁。NAPI (New Application Programming Interface)是一种中断和轮询相结合的技术。它在网络低负载时采用中断方式处理数据包,在高负载时只中断一次,随后采用轮询的方式处理多个数据包,流量采集 从而降低了中断次数。
NAPI 的基本思想是:首先硬件产生中断唤醒数据接收程序,然后使用轮询的方法获取数据。当一批数据包中的第一个数据包到达时,采用中断的方式通知系统,系统将接收设备注册到一个设备轮询队列中,并关闭对注册设备的中断响应。然后硬件中断处理程序激活一个软中断,在软中断期间对轮询队列中注册的网络设备执行轮询,从中读取数据包。采用配额的方法保证对各个网络设备的公平调度。配额是指网络设备每次发送或者接收的数据包上限,记为 P。例如网络设备接收了 P 个数据包后,设备的数据包接收缓冲区中仍然有数据,就将该设备重新注册到轮询队列的末尾,等待下一次轮询到该设备时再向内核提交数据包;接收缓冲区中没有数据则将该设备从轮询队列中注销,同时打开该设备的中断响应。
流量采集 NAPI 的基本工作流程是:
(1)网卡硬件接收到数据包之后由网卡的 DMA(Direct Memory Access) 引擎将数据映射网卡驱动的 Rx_ring 空间中,同时向 CPU 发起中断服务请求信号,执行中断服务程序 ISR。
(2)在中断服务程序中,首先关闭网卡的接收中断,调用 netif_rx_shcedule() 函数,在 Poll_list 表上登记网络设备,同时唤醒软中断,在软中断执行过程中网卡的接收中断始终处于关闭状态。
(3)在软中断处理程序中,调用 net_rx_action() 轮询 Poll_list 链表中的各个设备,获取每个设备 rx_ring 缓存中的所有数据包。Poll_list 上的所有设备都可以接收一定配额的包,如果设备 rx_ring 缓存中的数据包超出这个配额,则将该设备重新插入 Poll_list 队列尾部,等待下次轮询。如果数据包已收完,流量采集 则将设备从 Poll_list 中删除,并重新允许中断。
从 NAPI 的工作过程可以看出,NAPI 并非对每个接收包产生中断,只是当收到第一个包时,系统进入中断处理程序,然后采用轮询的方式处理 rx_ring 中的数据。
NAPI 技术本质上是为了降低中断产生的频率,特别是当链路中存在大量短长度数据包时,降低中断频率能够显著减少在中断现场的保护和恢复上的时间开销,腾出更多的计算资源用与网络层以上的数据包解码分析。NAPI 使系统在轻负载时性能趋近中断方式,响应速度较快。流量采集 当网络负载较低时,单位时间内到达网卡的数据包个数比较少,当只有一个数据包到达时,网卡将该数据包提交后就从轮询队列中注销设备,同时开中断等待下一个数据包到达,此时与中断处理方式一致。NAPI 技术在重负载时性能趋近轮询方式,响应速度较慢。当网络负载较高时,网卡每向内核提交一次数据包,就不断有新的数据包填充到接收缓冲区,使得接收缓冲区一直处于非空状态,此时网卡设备将始终处于轮询队列中而不会被注销,持续执行读取网络上的数据包和向上层应用提交数据包的工作。
相关信息: