- VxWorks設備驅動開發詳解
- 曹桂平等編著
- 3777字
- 2019-01-09 15:53:29
第5章 VxWorks下設備驅動的內核結構層次
本章將介紹VxWorks下設備驅動的結構層次,首先介紹I/O子系統下維護的三張表及相互之間的關系,而后對內核已有驅動支持進行說明,并介紹VxWorks下文件系統的支持,最后討論如何添加一個驅動到內核中。
5.1 認識VxWorks設備驅動內核基本層次
從上一章內容我們知道,底層設備驅動并不直接對用戶可見,還需要經過操作系統中間層作為“橋梁”進行交互。這個操作系統中間層根據具體的應用可能又被分為幾個子層次,我們將從用戶層開始到底層硬件設備之間的所有由內核提供的中間軟件層稱為內核驅動層次(注意:底層驅動也是內核的一部分)。
為了保持應用層用戶程序的平臺無關性,操作系統為應用層提供了一套標準的接口函數,這些接口函數在所有的平臺上都保持一致,只是隨著平臺的變化,底層驅動或接近驅動部分操作系統中間層可能會隨著調整。如此一來,可以使用戶程序脫離平臺,增加了應用層開發的效率,避免了重復編碼。通用操作系統下,將這套提供給應用層的標準接口函數從操作系統中獨立出來,專門以標準庫的形式存在,這樣更進一步增加了應用程序的平臺無關性,平臺之間的差別完全被操作系統屏蔽。
VxWorks下也對應用層提供了一套標準文件操作接口函數,實際上與通用操作系統提供的一致,我們將其稱作為標準I/O庫,VxWorks下由ioLib.c文件提供。ioLib.c文件提供如下標準接口函數:creat、open、unlink、remove、close、rename、read、write、ioctl、lseek、readv、writev等。VxWorks操作系統區別于通用操作系統的一個很大的不同點是:VxWorks下不區分用戶態和內核態,用戶層程序可以直接對內核函數進行調用,而無須使用指令中斷之類的機制或者存在使用權限上的限制。所以,VxWorks提供給應用層的接口無須通過外圍庫的方式,而是直接以內核文件的形式提供。用戶程序可以直接使用ioLib.c文件定義的如上這些函數,這些函數名稱與通用操作系統標準庫下的函數名一致,是VxWorks對標準庫的模擬。
由于是VxWorks內核提供,我們將ioLib.c文件中定義的如上這些函數看做是內核的一部分。ioLib.c文件提供的函數僅僅是一個最上層的接口,其并不完成具體的用戶請求,而是將請求進一步向其他內核模塊進行傳遞,位于ioLib.c模塊之下的模塊就是iosLib.c。我們將ioLib.c文件稱為上層接口子系統,將iosLib.c文件稱為I/O子系統,注意二者的區別。上層接口子系統直接對用戶層可見,而I/O子系統則一般不可見(當然用戶也可以直接調用iosLib.c中定義的函數,但一般需要做更多的封裝,且違背了內核提供的服務層次),其作為上層接口子系統與下層驅動系統的中間層而存在。如圖5-1所示顯示了內核驅動層次。

圖5-1 VxWorks內核驅動層次
從圖5-1中可以看出,I/O子系統在整個驅動層次中起著十分重要的作用,其對下管理著所有類型的設備驅動。換句話說,所有類型(包括網絡設備)的設備都必須向I/O子系統進行注冊方可被內核訪問。所以,在I/O子系統這一層次,內核維護著幾個十分關鍵的數組用以對設備驅動、設備本身以及當前系統文件句柄進行管理。
1.USB設備驅動內核層次
對于USB設備,通過USB I/O層驅動與I/O子系統進行交互,而與底層的交互則通過USB棧完成,HC驅動即主機USB控制器驅動,VxWorks內核提供UHCI、OHCI、EHCI三種標準USB主機控制器的驅動支持,但是在嵌入式平臺下有時會存在一個定制的USB主機控制器,此時可能需要編寫底層HC驅動。
2.塊設備驅動內核層次
塊設備從當前應用來看,主要分為兩大類:一類是長期以來使用的硬盤設備;另一類是Flash設備。硬盤設備驅動支持通過一個文件系統中間層,這個中間層在操作系統中十分關鍵,其對硬盤數據進行管理,提供硬盤數據的內核緩存區,避免頻繁訪問硬盤對整個系統性能造成非常不利的影響。對于硬盤這類塊設備,直接在文件系統層下通過一個硬盤驅動即可完成。另一類塊設備是Flash設備,Flash設備的最大特點是擦除次數有限,且擦除單元一般都較大,花費時間長,必須在文件系統層與Flash驅動層之間插入一個針對Flash設備這些特點的管理層,而且Flash設備每次寫入的數據塊相對硬盤設備都比較大,而在文件系統的統一管理下,我們需要將Flash設備模擬成一個硬盤設備,故在文件系統層和Flash驅動層還需要一個轉換層(或稱映射層),VxWorks內核提供TFFS(True Flash File System)中間層完成以上對Flash管理和映射的功能。TFFS中間層內部又進行分層,每層對應一個驅動文件,這一點在本書“Flash驅動”一章將有較詳細的討論。
3.字符設備驅動內核層次
字符設備即以字節流方式進行數據交互的設備,該類設備只能順序讀寫數據,不能像塊設備那樣對同一數據進行反復操作。如一個ADC設備,其接收外界檢波器模擬信號,轉換為數字信號,通過串行接口將數據送給CPU,此時就需要一個驅動對這個ADC設備進行驅動以獲取轉換后的數據。從圖5-1的層次來看,這個驅動將直接工作在I/O系統的管理之下。
串口設備本身也是一個字符設備,但是由于串口的使用范圍廣,為了提高串口驅動的編程效率以及串口數據的收發效率,VxWorks內核將串口設備與一般的字符設備區別對待,其提供一個TTY中間層驅動對串口數據進行管理(提供緩存)。TTY驅動向I/O系統注冊,底層串口設備驅動對TTY注冊。從底層驅動編程難易程度來看,TTY中間層的加入并非顯著降低了底層串口的編程難度,但是TTY中間層提供的一個最關鍵的優點是極大地提高了數據收發的效率,而且也提供了很大的靈活性,如提供較多的選項用以對串口設備進行控制。
4.網絡設備驅動內核層次
在第4章中,我們將設備類型從總體上分為了三類:字符設備、塊設備和網絡設備。其中字符設備和塊設備均由I/O子系統進行管理,而網絡設備由于其特殊的工作方式,將由另一套用戶層標準接口函數(套接字函數)和內核網絡棧進行支持。對于網絡設備驅動的支持,現在使用較多的是VxWorks提供的MUX接口,在MUX接口下編寫的底層網口驅動被稱為增強型網口驅動(Enhanced Network Driver,END)。網絡設備內核驅動層次如圖5-2所示。

圖5-2 網絡設備內核驅動層次
網絡數據由于其傳輸介質的不穩定性造成了網絡設備內核驅動層次和應用層接口層的特殊性。網絡編程應用層接口函數被稱為Socket(套接字),其區別于其他所有的設備編程使用的標準接口函數。為了在網絡上兩臺主機之間通信,我們首先必須約定一個協議,這樣發送方以這個事先約定好的協議封裝數據,接收方按這些協議進行解析,如此方能達到數據的傳送,如果二者沒有共同的協議作為約束,那么接收方根本就無法知道接收的報文中哪些是數據,哪些是為了使報文到達接收方的幫助信息。所以,網絡數據傳輸從一開始就好設計好一套網絡上所有的主機都必須遵守的通信協議。但是“一步到位”的協議設計方式為后期的擴展帶來了極大的不便,如果一個新的更有效的協議被發明,那么網絡上所有主機的網絡驅動都要進行修改,所以網絡協議從開始時就被設計為分層次的結構,每層使用本層上具有的協議對數據進行封裝。
最經典的當前使用范圍最廣的就是四層分層結構,從上到下依次為:應用層、傳輸層、網絡層、鏈路層。雖然OSI后來開發出了一個七層分層結構,但是基于四層分層結構的應用已經十分廣泛。當然OSI也考慮到這一點,所以七層分層結構在核心層上(傳輸、網絡、鏈路)設計成與四層分層結構兼容,這樣原先的四層實現只需在傳輸層實現之上插入一個模塊,即可完成對七層的支持,目前幾乎所有聲稱支持七層分層結構的實現都是這樣實現的。當然有些讀者可能會有疑問,為何設計分這么多層?原因在于:
● 網絡上傳輸一個報文不像主機內部傳遞一個報文,在網絡上傳輸的報文首先要指定目的主機的IP地址以及任務綁定的端口號,同時為了使得接收方可以驗證報文的合法性,還需要加上發送主機的IP地址以及報文發送任務綁定的端口號。
● 網絡接口設備接收報文并不以IP地址作為判斷依據,IP地址只是被操作系統網絡棧實現代碼使用,網絡接口設備使用硬件地址,在以太網下稱為MAC地址,一般是6B長度的字符串。所以,為了使一個主機能夠從網絡介質接收數據,報文中還必須提供網卡設備硬件地址。
● 為了共享網絡,網絡上每個主機每次發送的報文長度必須有限,然而用戶層一次發送的數據并不關心這一點,所以在發送報文前還必須對報文進行切割,將原先的一個報文切割成幾個報文分批發送,而在接收端又需要將這幾個報文進行重組后發送給相關進程,這些都需要在不同的層次完成。
● 網絡傳輸介質是不穩定的,可能有報文的丟失,不同的報文可能經過不同的傳輸路徑到達,故一個先發送的報文可能后到達等,這些問題都需要接收雙方進行考慮。所有的網絡棧必須設計成多個層次,每個層完成不同的功能,如果所有的功能都集中在一起實現,那么代碼將很復雜且不易維護和修改。分成多層可以在每層實現特定的功能,且在后期加入一個新的功能也較容易,不會對其他層的實現造成明顯的影響。網絡棧中“?!钡母拍罹褪瞧鹪从诓僮飨到y對于網絡報文的收發使用分層的結構。
網絡棧的實現是操作系統實現的一個固定組成部分,VxWorks在基本的網絡棧實現之下還實現了一個MUX接口層,專門與底層網絡設備驅動進行交互。MUX接口層將底層網絡設備驅動與核心網絡棧實現隔離開來,其提供的接口函數極大地降低了底層網絡設備驅動設計的復雜度,因為MUX層本身提供了一系列函數對網絡棧的請求進行了響應,而且也提供一些輔助函數供底層驅動進行調用,幫助進行一些輔助功能的實現。VxWorks將在MUX接口下實現的網絡設備驅動稱為END驅動,以區別于早期版中的BSD驅動,即直接實現在BSD網絡棧下的網絡設備驅動。
網絡傳輸方式下,由于需要對傳輸的數據經過分層次的特殊的封裝,且需要對網絡上兩臺主機之間通信的不穩定性進行處理,故網絡設備并不工作在I/O子系統下,而是使用完全不同的另一種機制,包括應用層接口函數都是獨立的一套函數集合。當然這種工作方式并非是VxWorks特有的,所有的操作系統對于網絡設備編程都采用與其他設備(字符和塊設備)不同的方式。當然所有的平臺對于網絡設備的處理都是基本一致的:應用層采用Socket編程接口,操作系統提供網絡棧實現和網絡設備驅動。