核心版本:Linux-2.6.34
網卡驅動:B4401
什麼是NAPI
NAPI是linux一套最新的處理網口資料的API,linux 2.5引入的,所以很多驅動並不支援這種操作方式。簡單來說,NAPI是綜合中斷方式與輪詢方式的技術。資料量很低與很高時,NAPI可以發揮中斷方式與輪詢方式的優點,效能較好。如果資料量不穩定,且說高不高說低不低,則NAPI會在兩種方式切換上消耗不少時間,效率反而較低一些。
下面會用到netdev_priv()這個函數,這裡先講解下,每個網卡驅動都有自己的私人的資料,來維持網路的正常運行,而這部分私人資料放在網路裝置資料後面(記憶體概念上),這個函數就是通過dev來取得這部分私人資料,注間這部分私人資料不在dev結構體中,而是緊接在dev記憶體空間後。
static inline void *netdev_priv(const struct net_device *dev) { return (char *)dev + ALIGN(sizeof(struct net_device), NETDEV_ALIGN); }
弄清這個函數還得先清楚dev這個結構的分配
alloc_netdev() -> alloc_netdev_mq() struct net_device *alloc_netdev_mq(int sizeof_priv, const char *name, void (*setup)(struct net_device *), unsigned int queue_count) { …… alloc_size = sizeof(struct net_device); if (sizeof_priv) { /* ensure 32-byte alignment of private area */ alloc_size = ALIGN(alloc_size, NETDEV_ALIGN); alloc_size += sizeof_priv; } /* ensure 32-byte alignment of whole construct */ alloc_size += NETDEV_ALIGN - 1; p = kzalloc(alloc_size, GFP_KERNEL); if (!p) { printk(KERN_ERR "alloc_netdev: Unable to allocate device./n"); return NULL; } ………. }
可以看到,dev在分配時,即在它的後面分配了private的空間,需要注意的是,這兩部分都是4位元組對齊的,如下圖所示,padding是加入的的補齊位元組:
舉個例子,假設sizeof(net_device)大小為31B,private大小45B,則實際分配空間如圖所示: