所謂的裝置輪詢機制實際上就是利用網絡卡驅動程式提供的napi機制加快網絡卡處理資料報的速度,因為在大流量的網路環境當中,標準的網絡卡中斷加上逐層的資料拷貝和系統呼叫會占用大量的cpu資源,而真正用於處理這些資料的資源卻很少。
乙個基本的想法是對於大流量網路,如果發現乙個dma傳輸中斷(這表明乙個網路資料通過dma通道到達了dma緩衝區),則首先關閉網絡卡的中斷模式,而對於隨後的資料全部採用輪詢方式進行接收,這樣大大降低了網絡卡的中斷次數,如果輪詢發現沒有資料報可收或者已經接收了一定數量的資料報,則開啟網絡卡的中斷模式,依次類推。
這種方法被證明在某種情況下能夠大大提高網路處理能力,但是在某種情況下會降低處理能力,因此並不是普遍適用的好的處理方法。另外,如果核心網路層資料報的處理方式仍然採用標準的方法(逐層拷貝並且產生一次系統呼叫,libpcap庫就是採用這種標準方式),那麼總體效率還是很低。必須考慮採用其它的優化措施降低網路層傳輸的記憶體拷貝次數及避免頻繁的系統呼叫。
為了達到上述的目標,提出了基於pf_ring套接字的裝置輪詢機制,另外還可以採用核心補丁rtirq,即實時中斷機制。
二、pf_ring套接字的實現
pf_ring套接字是作者為了減少網路層傳輸中的記憶體拷貝即避免頻繁的系統呼叫而設計的一種新的套接字型別,這種套接字採用模組方式動態載入。
為了能夠使得核心支援這種新的套接字型別,必須使用特定的核心補丁,該補丁增加了兩個檔案ring.h即ring_packet.c,分別定義了使用ring套接字的各種資料結構以及ring套接字的定義及處理函式。
該模組採用模組方式載入,模組初始化函式ring_init()在ring_packet.c中定義:
static int __init ring_init(void)
ring_table = null;
sock_register(&ring_family_ops);
set_ring_handler(my_ring_handler);
return 0;
pf_ring套接字的create()方法註冊為ring_create()函式:
static int ring_create(struct socket *sock, int protocol) else {
pfr->slots_info->tot_lost++;
write_unlock(&pfr->ring_index_lock);
/* wakeup in case of poll() */
if(waitqueue_active(&pfr->ring_slots_waitqueue))
wake_up_interruptible(&pfr->ring_slots_waitqueue);
五、後記
這部分內容是很久以後才補充的,因為工作一忙,我就立刻去救火,所有非工作必須的工作就一古腦的丟光了,現在只能匆匆收尾了,如果以後有這個需要,再來完善它吧。
當我分析pf_ring套接字時,是在2.4核心上打上補丁的,利用乙個特製的精簡版libpcap與pf_ring套接字結合使用,在網路抓包的測試中取得了相當不錯的效果,512位元組以上的tcp和udp資料幾乎可以達到前兆線速,而64位元組抓包情況下,由於我們當時的smartbits在500m流量下自己就丟包了,所以只測試了500m極限情況,同樣也是線速,後來我才用了核心零拷貝技術,修改了e1000網絡卡的驅動程式,測試以後的結果也不比pf_ring套接字強多少,從上面的分析中知道,其實pf_ring套接字的實現原理與零拷貝是一致的。
Linux 裝置驅動poll輪詢程式設計
linux系統下網路模型數select最為常用,當然,select只是檢測檔案系統資料狀態,並不只侷限於網路程式設計,select的功能需要底層驅動提供支援,其中核心應用即為等待佇列,其他模型,如poll和epoll,對驅動來說並無區別,驅動只是返回資料狀態而已。驅動支援select,需要實現fil...
我對基於裝置輪詢,PF RING機制的理解
我們在試驗中,採用了 napi 技術,pf ring 技術,mmap 技術,rtirq 技術。在網絡卡抓包的時候,未採用 napi 的程式在每個包到達時,由網絡卡硬體觸發核心中斷。這樣,如果在高流量 gbit 情況下,核心忙於處理由頻繁的中斷而引發的現場儲存和恢復,而無暇處理其他,導致包的丟失。現在...
新增裝置輪詢操作
private ifacilityservice facilitysrva servicelocator.get private ifacilityservice facilitysrvb servicelocator.get 需要生成兩個 類實體,不然同乙個 類實體的,兩次呼叫會是按序列化方式進行...