Linux 網路裝置驅動之層次結構

2021-07-01 19:31:17 字數 3025 閱讀 8325

學習網路裝置驅動之前,先來分析一下網路子系統的結構等知識。

1.分為使用者空間和核心空間,以及物理裝置空間;

2.使用者空間是應用層,核心空間與應用層互動的是系統檔案呼叫層(system call inte***ce),系統呼叫和網路協議層之間有個協議無關介面(protocol agnostic inte***ce),網路協議層和裝置驅動層(device dirver )之間有個裝置無關介面(device agnostic inte***ce);

3.為什麼要有協議無關介面?這樣系統呼叫可以用統一的介面來將不同型別的傳輸協議包送給協議無關介面,經過協議無關介面後來送給協議層處理,方便了應用層的系統呼叫。

4.為什麼要有裝置無關介面?這一層提供一組通用函式供底層驅動程式使用,讓它們可以對高層協議棧進行操作。向上,為我們的網路協議層來訪問裝置驅動提供了統一的介面,不管網絡卡驅動如何寫,我們的協議層訪問網絡卡驅動都是用的統一的介面;向下,它為裝置驅動程式處理協議提供了統一的介面,比如說網絡卡接收到了ip包,我們的驅動程式不需要去關心這個ip包是tcp的還是udp的,甚至它都不需要關心是不是ip包,它將這個包直接丟給裝置無關介面來處理了。

有了網路框架結構的了解,下面從

net_device

這個結構體來講起。

1.每個網路介面都由乙個net_device來描述,這個結構可以用alloc_netdev或者alloc_etherdev()來分配;

2.這個結構體主要的成員有 

網路介面驅動的註冊方式與字元驅動不同的地方是它沒有主次裝置號,用register_netdev(struct net_device*dev)註冊

剛才提到裝置無關介面,那麼它為網路協議層提供統一的資料報收發介面,不論上層協議為arp還是ip,都通過dev_queue_xmit(struct sk_buff*skb)函式傳送資料,並且通過netif_rx(struct sk_buff*skb)函式來接受資料,說到這兒,

我們要引入套接字緩衝區

struct sk_buff

這個非常重要的結構體

了。該結構主要的成員如下:unsigned char*head;unsigned char*end;unsigned char*data;unsigned char*end;

head                                  data                     tail                           end

分配空間的開始             有效資料的開始      有效資料的結尾       分配空間的結束

skb_buff 的操作函式主要有struct sk_buff *dev_alloc_skb(unsigned int len, int priority) ----------------供驅動**使用

struct sk_buff *alloc_skb(unsigned int len, int priority)        -------------供協議棧**使用

另外三個操作函式分別是unsigned char*skb_put(struct sk_buff *skb, int len)和unsigned                                                char*skb_push(struct sk_buff *skb, int len),以及static inline void skb_reserve(struct sk_buff *skb, int                        len)。skb_put的作用是將data指標前移len的長度,函式返回的是移動之後的指標;而skb_push的作用                        是將tail指標往後移len的長度,並且返回的是移動之前的指標;skb_reserve的作用是將data和tail的指標                        同時向後移動len的長度。

skb_buff的釋放函式dev_kfree_skb(struct sk_buff *skb);

下面是網路裝置驅動的註冊與登出

先alloc_etherdev(sizeof_pri)函式來對net_device的生成和對其成員的賦值,它是alloc_netdev()針對乙太網的快捷函式,分配並賦值後用register_netdev()註冊裝置進核心。net_device結構體的分配與驅動註冊是在模組載入函式中進行。同理,釋放函式free_netdev()和登出函式unregister_netdev()是在模組解除安裝函式中完成。

網路裝置驅動註冊,當尋找到device時,會去執行probe函式,此時我們的網路裝置的初始化工作可以放在probe函式中去執行。具體的初始化主要包含以下幾個方面:

網路裝置的開啟函式需要完成如下的工作:

網路裝置的關閉函式需要完成如下的工作:

linux網路子系統傳送資料報時,會呼叫驅動程式提供的hard_start_transmit()函式,在裝置初始化的時候這個函式指標需要被初始化。hard_start_transmit()函式中,根據skb->data,skb->len來傳送資料,當傳送佇列滿了,或者其他原因來不及傳送當前上層傳下來的包時,我們呼叫netif_stop_queue()函式來阻止上層繼續向網路裝置驅動傳送資料報。當忙於傳送的資料報傳送完成後,傳送結束的中斷處理中,應該呼叫netif_wake_queue喚醒被阻塞的上層。

當資料傳輸超時時,此時超時處理函式***_tx_timeout()將會被呼叫,這個函式裡面也需要呼叫linux核心提供的netif_wake_queue()函式重新啟動裝置傳送佇列。

網路接收資料報的主要方法是中斷引發裝置的中斷處理函式,中斷處理判斷中斷型別,如果為接收中斷則讀取接收到的資料,分配sk_buff資料結構,將資料複製到資料緩衝區,並且呼叫netif_rx()函式傳遞給上層協議。我們經常在接收函式中看到skb=dev_alloc_skb(length+2);skb_reserve(skb,2),這裡的2是因為ip協議頭是4位元組對齊的,而接收到的ip頭首部是6個位元組目的位址,6個位元組源位址,2個位元組資料字段長度,一共加起來是14個位元組,所以分配skb資料緩衝區的時候多分配2個位元組。

linux網路裝置驅動

linux網路裝置驅動 linux網路驅動程式的體系結構可劃分為4個層次。linux核心源 中提供了網路裝置介面及以網路子系統的上層的 移植特定網路硬體的驅動程式的主要工作就是完成裝置驅動功能層的相應 根據底層具體的硬體特性,定義網路裝置介面struct net device型別的結構體變數,並實現...

linux 網路裝置驅動

linux 網路驅動 謹以此文紀念過往的歲月 一.前言 在linux中網路驅動也是乙個大頭,如何去理解網路驅動是作為乙個linux驅動工程師必備的技能。不過同樣的裝置,在不同人的手中會有不同的效果,其原因就在於驅動的好與否。二.裝置註冊 學習網路的驅動與學習普通cdev驅動一樣,都是學習其模板,然後...

Linux網路裝置驅動 一

一 網路裝置驅動基礎 1.乙太網基礎理論 乙太網是區域網的一種,它使用載波監聽多路訪問及衝突檢測技術 csma cd 並以10m s的速率執行在多種型別的電纜上,常用的網絡卡晶元有dm9000 dm9161 cs8900晶元。乙太網的拓撲結構有匯流排型和星型,乙太網的工作模式有半雙工和全雙工。目前雙...