linux内核包转发过程--NIC帧接收分析
每一个cpu都有队列来处理接收到的帧。都有其数据结构来处理入口和出口流量,因此。不同cpu之间没有必要使用上锁机制。。
此队列数据结构为softnet_data(定义在include/linux/netdevice.h中):
非NAPI设备驱动会为其所接收的每个帧产生一个中断事件,在高流量负载下,会花掉大量时间处理中断事件,造成资源浪费。
而NAPI驱动混合了中断事件和轮询。在高流量负载下其性能会比旧方法要好。 NAPI主要思想是混合使用中断事件和轮询。而不是只使用中断事件驱动模型。当收到新的帧时。关中断。再一次处理全然部入口队列。
从内核观点来看。NAPI方法由于中断事件少了。降低了cpu负载。
【文章福利】小编推荐自己的Linux内核技术交流群:【891587639】整理了一些个人觉得比较好的学习书籍、视频资料共享在群文件里面,有需要的可以自行添加哦!!!(含视频教程、电子书、实战项目及代码)


使用非NAPI的驱动程序的xx_rx()函数一般例如以下:
第一步是分配一个缓存区来保存报文。
注意缓存分配函数 (dev_alloc_skb) 须要知道数据长度。
第二步将报文数据被复制到缓存区; skb_put 函数更新缓存中的数据末尾指针并返回指向新建空间的指针。
第三步提取协议标识及获取其它信息。
最后调用netif_rx(skb)做进一步处理。该函数一般定义在net/core/dev.c中。
至此中断的上半部完毕,其它的工作交由下半部来实现。napi_schedule(&queue->backlog)函数将有等待的接收数据包的NIC链入softnet_data的poll_list队列。然后触发软中断,让下半部去完毕数据的处理工作。 而是用NAPI设备的接受数据时直接触发软中断,不须要通过netif_rx()函数设置好接收队列再触发软中断。
比方e100硬中断处理函数为:
在前面我们已经知道在net_dev_init()函数中注冊了收报软中断函数net_rx_action(),当软中断被触发之后。该函数将被调用。
net_rx_action()函数为:
对NAPI设备来的说,驱动程序必须提供一个poll方法,poll 方法有以下原型: int (*poll)(struct napi_struct *dev, int *budget); 在初始化时须要加入该方法: netif_napi_add(netdev, &nic->napi, xx_poll, XX_NAPI_WEIGHT);
NAPI驱动 的 poll 方法实现一般例如以下(借用《Linux设备驱动程序》中代码,内核有点没对上,懒得去写了):
NAPI驱动提供自己的poll函数和私有队列。 无论是非NAPI或NAPI,他们的poll函数最后都会调用netif_receive_skb(skb)来处理接收到的帧。
该函数会想各个已注冊的协议例程发送一个skb。之后数据进入Linux内核协议栈处理。
