我正在寫一個linux網(wǎng)卡零拷貝的驅(qū)動,是在intel e1000驅(qū)動基礎(chǔ)之上改動。
查了查資料已經(jīng)搞清楚DMA是如何運作,而且也知道如何使DMA將數(shù)據(jù)直接寫入自己申請的內(nèi)存空間。已經(jīng)有了一個大致的解決方案,但有以下下幾個細(xì)節(jié)搞不定,請同學(xué)們幫幫。
我先說下我的思路: 首先從用戶太說起,數(shù)據(jù)包從經(jīng)數(shù)據(jù)線至網(wǎng)卡驅(qū)動至協(xié)議棧最后至用戶太要經(jīng)過至少兩次拷貝才能完成,期間cpu參與過多,造成cpu負(fù)擔(dān)過重,效率低下。
從e1000的驅(qū)動看到:pci_map_single()這個函數(shù)完成了將內(nèi)核內(nèi)存映射到DMA設(shè)備的過程。我所做的就是將pci_mag_single()映射的內(nèi)存替換成我申請的內(nèi)存。這樣DMA設(shè)備就把數(shù)據(jù)直接寫到指定的內(nèi)存了,用戶臺進(jìn)程讀這塊內(nèi)存就OK了。其中沒有cpu的參與。
如何替換呢?寫過內(nèi)核的同學(xué)們都知道skb buffer這個東西。當(dāng)網(wǎng)卡驅(qū)動被初始化的時候,會netdev_alloc_skb這個系統(tǒng)函數(shù),預(yù)先申請一堆的skb buffer。
從源碼中看出,申請過程分兩個過程,首先申請一個skb buffer結(jié)構(gòu)。skb buffer中有一個指針類型的成員變量data,此時的data是沒有指向任何有效數(shù)據(jù)塊的。然后在用kmalloc()申請一塊內(nèi)存,賦給skb->data。網(wǎng)卡驅(qū)動就是用pci_map_single()將skb->data映射入DMA設(shè)備。然后DMA設(shè)備會將收到的數(shù)據(jù)直接寫入skb->data指向的內(nèi)存區(qū)。
所以我們只需增加一個內(nèi)存分配模塊,替換網(wǎng)卡驅(qū)動skb buffer的分配函數(shù)即可。那是DMA設(shè)備會自動的將收到的數(shù)據(jù)寫入我們指定的內(nèi)存中。 以上是我的思路。不對的地方請指正。
下面是我的問題。 DMA將數(shù)據(jù)寫入我們分配的內(nèi)存后,就需要通知用戶態(tài)的進(jìn)程來讀取了。問題如下:
1.用戶態(tài)如何讀取這部分內(nèi)存。 我查了查資料,有兩種方式可以完成。a.使用proc的方式。b.使用ioctrl的方式。由于數(shù)據(jù)量過大,我希望采用proc的方式。但是對于proc的方式我很不理解。從資料中看到的是在驅(qū)動初始化時使用create_proc_entry這個函數(shù),在/proc/目錄下建立一個虛擬文件。用戶態(tài)進(jìn)程讀這個虛擬文件就行了。
struct proc_dir_entry *create_proc_entry(constchar*name, mode_t mode,struct proc_dir_entry *parent)
這個函數(shù)會在/proc目錄下建立一個文件,OK,沒有問題。然后呢,用戶態(tài)的程序去讀該文件,讀什么呢,文件建立后里面并沒有寫入任何有用的東西。我就猜也許是要我自己把我申請的物理內(nèi)存首地址以及內(nèi)存大小寫入到這個文件中吧。用戶態(tài)讀取文件中的物理地址,使用mmap將物理內(nèi)存地址映射入自己的進(jìn)程空間。
這個想發(fā)不知對不對。如果不對,請同學(xué)給我指明一個思路,謝謝。
2.將內(nèi)核空間成功映射入用戶態(tài)進(jìn)程空間后,網(wǎng)卡驅(qū)動如何同用戶態(tài)的進(jìn)程同步。 我是這樣實現(xiàn)的,我在內(nèi)核申請了塊內(nèi)存,作為隊列。接收過來的數(shù)據(jù)會被放入隊列中。驅(qū)動和用戶態(tài)進(jìn)程肯定要競爭這個隊列,如何同步呢。
3.內(nèi)核中的內(nèi)存形式。 用戶態(tài)進(jìn)程都有自己的虛擬空間,用戶態(tài)進(jìn)程是否有類似的概念呢。還是說內(nèi)核空間就是被所有內(nèi)核模塊,內(nèi)核進(jìn)程所共享的。我看得書中并沒有類似概念的說明,請同學(xué)們給我掃掃盲。
4.一臺機(jī)器上會有多塊型號相同的網(wǎng)卡,那么這些網(wǎng)卡會使用同樣的驅(qū)動。 比如有a,b,c三塊網(wǎng)卡,型號相同。 a網(wǎng)卡首先被激活,申請一塊內(nèi)存。然后b,c網(wǎng)卡也被激活。a網(wǎng)卡申請的內(nèi)存會被b.c網(wǎng)卡使用嗎。
同學(xué)們一起交流,共同提高。 謝謝。 |