Linux 網絡卡驅動學習(五)(收發包具體過程)

2021-07-10 02:23:46 字數 3073 閱讀 1971

裝置初始化函式

網路裝置驅動在 linux 核心中是以核心模組的形式存在的,對應於模組的初始化,需要提供乙個初始化函式來初始化網路裝置的硬體暫存器、配置 dma 以及初始化相關核心變數等。裝置初始化函式在核心模組被載入時呼叫,它的函式形式如下:

static int __init xx_init (void)  

module_init(xx_init); // 這句話表明模組載入時自動呼叫 xx_init 函式

裝置初始化函式主要完成以下功能:

1. 硬體初始化

因為網路裝置主要分為 phy、mac 和 dma 三個硬體模組,開發者需要分別對這三個模組進行初始化。

初始化 phy 模組,包括設定雙工 / 半雙工執行模式、裝置執行速率和自協商模式等。

初始化 mac 模組,包括設定裝置介面模式等。

初始化 dma 模組,包括建立 bd 表、設定 bd 屬性以及給 bd 分配快取等。

2. 核心變數初始化

初始化並註冊核心裝置。核心裝置是屬性為 net_device 的乙個變數,開發者需要申請該變數對應的空間(通過 alloc_netdev 函式)、設定變數引數、掛接介面函式以及註冊裝置(通過 register_netdev 函式)。

常用的掛接介面函式如下:

net_device *dev_p; 

dev_p->open = xx_open; // 裝置開啟函式

dev_p->stop = xx_stop; // 裝置停止函式

dev_p->hard_start_xmit = xx_tx; // 資料傳送函式

dev_p->do_ioctl = xx_ioctl; // 其它的控制函式

……

資料收發函式

資料的接收和傳送是網路裝置驅動最重要的部分,對於使用者來說,他們無需了解當前系統使用了什麼網路裝置、網路裝置收發如何進行等,所有的這些細節對於使用者都是遮蔽的。linux 使用 socket 做為連線使用者和網路裝置的乙個橋梁。使用者可以通過 read / write 等函式操作 socket,然後通過 socket 與具體的網路裝置進行互動,從而進行實際的資料收發工作。

linux 提供了乙個被稱為 sk_buff 的資料介面型別,使用者傳給 socket 的資料首先會儲存在 sk_buff 對應的緩衝區中,sk_buff 的結構定義在 include/linux/skbuff.h 檔案中。它儲存資料報的結構示意圖如下所示。

圖 4. sk_buff 資料結構圖

當使用者呼叫 socket 開始傳送資料時,資料被儲存到了 sk_buff 型別的快取中,網路裝置的傳送函式(裝置初始化函式中註冊的 hard_start_xmit)也隨之被呼叫,流程圖如下所示。

圖 5. 資料傳送流程圖

socket 介面呼叫網路裝置傳送函式(hard_start_xmit),hard_start_xmit 已經在初始化過程中被掛接成類似於 xx_tx 的具體的傳送函式,xx_tx 主要實現如下步驟。

從傳送 bd 表中取出乙個空閒的 bd。

根據 sk_buff 中儲存的資料修改 bd 的屬性,乙個是資料長度,另乙個是資料報快取指標。值得注意的是,資料報快取指標對應的必須是實體地址,這是因為 dma 在獲取 bd 中對應的資料時只能識別儲存該資料快取的實體地址。

bd_p->length = skb_p->len; 

bd_p->bufptr = virt_to_phys(skb_p->data);

修改該 bd 的狀態為就緒態,dma 模組將自動傳送處於就緒態 bd 中所對應的資料。

移動傳送 bd 表的指標指向下乙個 bd。

dma 模組開始將處於就緒態 bd 快取內的資料傳送至網路中,當傳送完成後自動恢復該 bd 為空閒態。

2. 資料接收流程

當網路裝置接收到資料時,dma 模組會自動將資料儲存起來並通知處理器來取,處理器通過中斷或者輪詢方式發現有資料接收進來後,再將資料儲存到 sk_buff 緩衝區中,並通過 socket 介面讀出來。流程圖如下所示。

圖 6. 資料接收流程圖

處理器可以通過中斷或者輪詢的方式檢查接收 bd 表的狀態,無論採用哪種方式,它們都需要實現以下步驟。

從接收 bd 表中取出乙個空閒的 bd。

如果當前 bd 為就緒態,檢查當前 bd 的資料狀態,更新資料接收統計。

從 bd 中取出資料儲存在 sk_buff 的緩衝區中。

更新 bd 的狀態為空閒態。

移動接收 bd 表的指標指向下乙個 bd。

使用者呼叫 read 之類的讀函式,從 sk_buff 緩衝區中讀出資料,同時釋放該緩衝區。

linux 核心在接收資料時有兩種方式可供選擇,一種是中斷方式,另外一種是輪詢方式。

中斷方式

如果選擇中斷方式,首先在使用該驅動之前,需要將該中斷對應的中斷型別號和中斷處理程式註冊進去。網路裝置驅動在初始化時會將具體的 xx_open 函式掛接在驅動的 open 介面上,xx_open 函式掛接中斷的步驟如下。

request_irq(rx_irq, xx_isr_rx, …… ); 

request_irq(tx_irq, xx_isr_tx, …… );

網路裝置的中斷一般會分為兩種,一種是傳送中斷,另一種是接收中斷。核心需要分別對這兩種中斷型別號進行註冊。

傳送中斷處理程式(xx_isr_tx)的工作主要是監控資料傳送狀態、更新資料傳送統計等。

接收中斷處理程式(xx_isr_rx)的工作主要是接收資料並傳遞給協議層、監控資料接收狀態、更新資料接收統計等。

對於中斷方式來說,由於每收到乙個包都會產生乙個中斷,而處理器會迅速跳到中斷服務程式中去處理收包,因此中斷接收方式的實時性高,但如果遇到資料報流量很大的情況時,過多的中斷會增加系統的負荷。

輪詢方式

如果採用輪詢方式,就不需要使能網路裝置的中斷狀態,也不需要註冊中斷處理程式。作業系統會專門開啟乙個任務去定時檢查 bd 表,如果發現當前指標指向的 bd 非空閒,則將該 bd 對應的資料取出來,並恢復 bd 的空閒狀態。

由於是採用任務定時檢查的原理,從而輪詢接收方式的實時性較差,但它沒有中斷那種系統上下文切換的開銷,因此輪詢方式在處理大流量資料報時會顯得更加高效。

網絡卡驅動收發包過程

網絡卡工作在物理層和資料鏈路層,主要由phy mac晶元 tx rx fifo dma等組成,其中網線通過變壓器接phy晶元 phy晶元通過mii接mac晶元 mac晶元接pci匯流排 phy晶元主要負責 csma cd 模數轉換 編譯碼 串並轉換 mac晶元主要負責 intel的千兆網絡卡以825...

網絡卡驅動收發包過程

網絡卡工作在物理層和資料鏈路層,主要由phy mac晶元 tx rx fifo dma等組成,其中網線通過變壓器接phy晶元 phy晶元通過mii接mac晶元 mac晶元接pci匯流排 phy晶元主要負責 csma cd 模數轉換 編譯碼 串並轉換 mac晶元主要負責 位元流和幀的轉換 7位元組的前...

網絡卡驅動收發包過程

網絡卡工作在物理層和資料鏈路層,主要由phy mac晶元 tx rx fifo dma等組成,其中網線通過變壓器接phy晶元 phy晶元通過mii接mac晶元 mac晶元接pci匯流排 phy晶元主要負責 csma cd 模數轉換 編譯碼 串並轉換 mac晶元主要負責 intel的千兆網絡卡以825...