Linux作業系統網路驅動程式編寫1

來源:互聯網
上載者:User

2.1 網路驅動程式的結構
所有的Linux網路驅動程式遵循通用的介面。設計時採用的是物件導向的方法。
一個裝置就是一個對象(device 結構),它內部有自己的資料和方法。每一個裝置的
方法被調用時的第一個參數都是這個裝置對象本身。這樣這個方法就可以存取自身
的資料(類似物件導向程式設計時的this引用)。
一個網路裝置最基本的方法有初始化、發送和接收。

------------------- ---------------------
|deliver packets | |receive packets queue|
|(dev_queue_xmit()) | |them(netif_rx()) |
------------------- ---------------------
| | / \\
\\ / | |
-------------------------------------------------------
| methods and variables(initialize,open,close,hard_xmit,|
| interrupt handler,config,resources,status...) |
-------------------------------------------------------
| | / \\
\\ / | |
----------------- ----------------------
|send to hardware | |receivce from hardware|
----------------- ----------------------
| | / \\
\\ / | |
-----------------------------------------------------
| hardware media |
-----------------------------------------------------

初始化程式完成硬體的初始化、device中變數的初始化和系統資源的申請。發送
程式是在驅動程式的上層協議層有資料要發送時自動調用的。一般驅動程式中不對發
送資料進行緩衝,而是直接使用硬體的發送功能把資料發送出去。接收資料一般是通
過硬體中斷來通知的。在中斷處理常式裡,把硬體幀資訊填入一個skbuff結構中,然 後調用netif_rx()傳遞給上層處理。

2.2 網路驅動程式的基本方法
網路裝置做為一個對象,提供一些方法供系統訪問。正是這些有統一介面的方法,
掩蔽了硬體的具體細節,讓系統對各種網路裝置的訪問都採用統一的形式,做到硬體
無關性。
下面解釋最基本的方法。
2.2.1 初始化(initialize)
驅動程式必須有一個初始化方法。在把驅動程式載入系統的時候會調用這個初
始化程式。它做以下幾方面的工作。檢測裝置。在初始化程式裡你可以根據硬體的
特徵檢查硬體是否存在,然後決定是否啟動這個驅動程式。配置和初始化硬體。在
初始化程式裡你可以完成對硬體資源的配置,比如隨插即用的硬體就可以在這個時
候進行配置(Linux核心對PnP功能沒有很好的支援,可以在驅動程式裡完成這個功
能)。配置或協商好硬體佔用的資源以後,就可以向系統申請這些資源。有些資源是
可以和別的裝置共用的,如中斷。有些是不能共用的,如IO、DMA。接下來你要初始
化device結構中的變數。最後,你可以讓硬體正式開始工作。

2.2.2 開啟(open)
open這個方法在網路裝置驅動程式裡是網路裝置被啟用的時候被調用(即裝置狀
態由down-->up)。所以實際上很多在initialize中的工作可以放到這裡來做。比如資
源的申請,硬體的啟用。如果dev->open返回非0(error),則硬體的狀態還是down。
Open方法另一個作用是如果驅動程式做為一個模組被裝入,則要防止模組卸載時
裝置處於開啟狀態。在open方法裡要調用MOD_INC_USE_COUNT宏。

2.2.3 關閉(stop)
close方法做和open相反的工作。可以釋放某些資源以減少系統負擔。Close是在
裝置狀態由up轉為down時被調用的。另外如果是做為模組裝入的驅動程式,close裡
應該調用MOD_DEC_USE_COUNT,減少裝置被引用的次數,以使驅動程式可以被卸載。
另外close方法必須返回成功(0==success)。

2.2.4 發送(hard_start_xmit)
所有的網路裝置驅動程式都必須有這個發送方法。在系統調用驅動程式的xmit
時,發送的資料放在一個sk_buff結構中。一般的驅動程式把資料傳給硬體發出去。
也有一些特殊的裝置比如loopback把資料群組成一個接收資料再回送給系統,或者
dummy裝置直接丟棄資料。
如果發送成功,hard_start_xmit方法裡釋放sk_buff,返回0(發送成功)。如果
裝置暫時無法處理,比如硬體忙,則返回1。這時如果dev->tbusy置為非0,則系統
認為硬體忙,要等到dev->tbusy置0以後才會再次發送。Tbusy的置0任務一般由中斷
完成。硬體在發送結束後產生中斷,這時可以把tbusy置0,然後用mark_bh()調用通
知系統可以再次發送。在發送不成功的情況下,也可以不置dev->tbusy為非0,這樣
系統會不斷嘗試重發。如果hard_start_xmit發送不成功,則不要釋放sk_buff。
傳送下來的sk_buff中的資料已經包含硬體需要的幀頭。所以在發送方法裡不需
要再填充硬體幀頭,資料可以直接提交給硬體發送。Sk_buff是被鎖住的(locked),
確保其他程式不會存取它。

2.2.5 接收(reception)
驅動程式並不存在一個接收方法。有資料收到應該是驅動程式來通知系統的。
一般裝置收到資料後都會產生一個中斷,在中斷處理常式中驅動程式申請一塊
sk_buff(skb),從硬體讀出資料放置到申請好的緩衝區裡。接下來填充sk_buff中
的一些資訊。Skb->dev = dev,判斷收到幀的協議類型,填入skb->protocol(多協
議的支援)。把指標skb->mac.raw指向硬體資料然後丟棄硬體幀頭(skb_pull)。還要
設定skb->pkt_type,標明第二層(鏈路層)資料類型。可以是以下類型:
PACKET_BROADCAST : 鏈路層廣播
PACKET_MULTICAST : 鏈路層組播
PACKET_SELF : 發給自己的幀
PACKET_OTHERHOST : 發給別人的幀(監聽模式時會有這種幀)

最後調用netif_rx()把資料傳送給協議層。Netif_rx()裡資料放入處理隊列然後返
回,真正的處理是在中斷返回以後,這樣可以減少停機時間。調用netif_rx()以後,
驅動程式就不能再存取資料緩衝區skb。

2.2.6 硬體幀頭(hard_header)
硬體一般都會在上層資料發送之前加上自己的硬體幀頭,比如乙太網路(Ethernet)
就有14位元組的幀頭。這個幀頭是加在上層ip、ipx等資料包的前面的。驅動程式提供
一個hard_header方法,協議層(ip、ipx、arp等)在發送資料之前會調用這段程式。
硬體幀頭的長度必須填在dev->hard_header_len,這樣協議層回在資料之前保留好
硬體幀頭的空間。這樣hard_header程式只要調用skb_push然後正確填入硬體幀頭就
可以了。
在協議層調用hard_header時,傳送的參數包括(2.0.xx):資料的sk_buff,
device指標,protocol,目的地址(daddr),源地址(saddr),資料長度(len)。資料
長度不要使用sk_buff中的參數,因為調用hard_header時資料可能還沒完全組織好。
Saddr是NULL的話是使用預設地址(default)。Daddr是NULL表明協議層不知道硬體目
的地址。如果hard_header完全填好了硬體幀頭,則返回添加的位元組數。如果硬體幀
頭中的資訊還不完全(比如daddr為NULL,但是幀頭中需要目的硬體地址。典型的情
況是乙太網路需要位址解析(arp)),則返回負位元組數。Hard_header返回負數的情況
下,協議層會做進一步的build header的工作。目前Linux系統裡就是做arp
(如果hard_header返回正,dev->arp=1,表明不需要做arp,返回負,dev->arp=0,
做arp)。
對hard_header的調用在每個協議層的處理常式裡。如ip_output。

2.2.7 位址解析(xarp)
有些網路有硬體地址(比如Ethernet),並且在發送硬體幀時需要知道目的硬體
地址。這樣就需要上層協議地址(ip、ipx)和硬體地址的對應。這個對應是通過地址
解析完成的。需要做arp的的裝置在發送之前會調用驅動程式的rebuild_header方
法。調用的主要參數包括指向硬體幀頭的指標,協議層地址。如果驅動程式能夠解
析硬體地址,就返回1,如果不能,返回0。
對rebuild_header的調用在net/core/dev.c的do_dev_queue_xmit()裡。

2.2.8 參數設定和統計資料
在驅動程式裡還提供一些方法供系統對裝置的參數進行設定和讀取資訊。一般
只有超級使用者(root)許可權才能對裝置參數進行設定。設定方法有:
dev->set_mac_address()
當使用者調用ioctl類型為SIOCSIFHWADDR時是要設定這個裝置的mac地址。一般
對mac地址的設定沒有太大意義的。
Dev->set_config()

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.