1. 减少中断
高速网络每秒能产生上千次中断,每次中断都是告诉内核已经知道的事情:有很多包要处理。NAPI允许驱动在禁止中断的情况下运行,以此来减小系统负载。
2. 尽早丢弃包
系统必须要丢弃那些来不及处理包时。但是丢弃前我们要尽量少花时间处理这些它们。与NAPI兼容的驱动能够在网络适配层丢弃这些处理不了的包,内核根本就看不见它们。
NAPI首先集成到了2.5/2.6内核,不过也已经移植到了2.4内核。需要注意的是NAPI完全是可选的,驱动程序没有它也能工作的很好,只是可能会慢些。用以前2.4内核写的驱动在新内核中仍然可以工作。
NAPI驱动程序设计:
当有新包到达并且产生中断后,驱动应该禁止任何“新包到达”的中断,并且让网络子系统轮询以尽可能多的得到随后到达的包。通过以下接口让驱动轮询:
void netif_rx_schedule(struct net_device *dev);
下一步是创建poll()方法;它的功能是将从网卡得到包传给内核。原型如下:
int (*poll)(struct net_device *dev, int *budget);
poll能得到的包的个数由budget来限制,Linux在net/core/dev.c中将其设置为300。
得到的包不应该交给老的接口netif_rx()来处理,应该用新接口:
int netif_receive_skb(struct sk_buff *skb);
当所有包都处理完后由下面的接口开启中断,禁止轮询:
void netif_rx_complete(struct net_device *dev);
二、在Solaris 8和Solaris 9的多处理器系统中,处理器的速度滞后于千兆网卡速度。为了缓解一个CPU忙于处理中断而其他CPU无事可做的情况,Solaris引进了一个叫做工作者的线程模型。也就是由一个或多个工作者线程将工作分发给多个CPU,而不是仅仅由被中断的CPU来处理所有得到的包。但是设备驱动自己也不知道应该创建多少个工作者线程;如果系统有多个网卡处于活动状态事情就更复杂了;当10G网卡出现后,而以太网包大小仍然是1500字节时,事情就更糟糕了。系统每秒能得到80000个包,仅留下12微秒给CPU处理它们。
于是Solaris 10引进了一种新的框架,GLDv3(General LAN Driver version 3)。思想和NAPI是一致的,只不过Solaris更擅长于多处理系统。
三、目前我还不清楚究竟是Solaris先引进的GLDv3还是Linux先引进的NAPI,或者同时。但是可以肯定的是Linux的slab内存分配算法还有模块化的思想都是从Solaris借鉴过来的。不过Linux开始的时候就是一个UNIX克隆。但是我们也看到Solaris已经移植了大量的 Linux应用软件,包括桌面系统,gcc编译器,游戏,音视频软件等等。虽然Linux服务器占有率远远高于Solaris,但是Oracle的首选平台依然是Solaris,我也相信世界500强的大公司也是不会吝惜的选择Linux+MySQL+php的;虽然Solaris已经移植了大量 Linux应用程序,但是要想直接编译最新的源代码依然不太现实。所以我觉得存在的都是合理的,完全没有必要厚此薄彼,重要的是作出适合自己的选择。 BSD之所以依然有大量的跟随者肯定也是和它出色的安全性分不开的,不是说国防科大搞的麒麟操作系统抄的就是BSD吗。
参考资料:
http://linux-net.osdl.org/index.php/NAPI
Solris Internals
