WDM內核驅動程序模型分析
更新時間: 2007-02-08 01:59:33來源: 粵嵌教育瀏覽量:1733
WDM內核驅動程序模型分析
WDM驅動程序是Windows 2000操作系統重要的組成部分,它的正常工作需要有Windows 2000其它內核組件的支持,同時大部分的內核組件也必須同WDM驅動程序交互來完成它們的功能,為能夠完整而清晰的說明WDM驅動程序的工作情況,本文首先說明Windows 2000操作系統的內核工作機理,同時將給出WDM驅動程序和內核其它組件的協同工作機制,分析WDM驅動程序的結構和工作流程。
1 Windows 2000內核組件工作模式
1.1 Windows 2000的設計思想
在現代操作系統中,應用程序和操作系統本身是分開的――操作系統代碼運行在核心態并有權訪問系統數據和硬件;應用程序運行在用戶態,能夠使用的接口和訪問系統數據的權限都受到限制。當用戶程序調用系統服務時,處理器捕獲該調用,然后把調用的線程切換到核心態。當系統服務完成后,操作系統將線程描述表切換回用戶態,允許調用者繼續運行。
系統核心態部分的設計是豐富多樣的。較典型的有以下幾種:
A) 傳統的單片式操作系統。
系統被設計為一個單一的、龐大的軟件系統,在內部組件之間有許多關聯。這種軟件系統依賴于許多系統組件。這種相互關聯意味著要擴展系統,就需要對全部代碼庫進行大量修改。同時在單片式操作系統中大量的操作系統代碼運行于同一內存空間,這就意味著任何操作系統組件都可能損壞正在被其它組件使用數據。
B) 分片式的操作系統。
將操作系統發分為不同層次中的模塊。每個模塊提供一組功能函數其它模塊調用。在某一層次上的代碼只能調用較低層次上的代碼。在一些了系統中,DEC公司的OpenVMS包括老的Multics操作系統,硬件甚至強制分層(使用多重、分級處理模式)。分層操作系統結構的優點是,由于每層代碼只能訪問較低層的接口(和數據結構),因此限制了使用無限權利的代碼數量,這種結構也允許在層開始調試操作系統,然后一層一層的往上調試,直到整個操作系統工作正常。層次化結構也使增強操作系統更容易,因為修改或替代單獨的一層,不影響系統的其它部分。
C) 客戶服務器微內核模型。
其思想是把操作系統分成若干個服務器進程,每個服務器進程完成一種服務,如內存管理服務、進程創建服務和處理器調度服務。每個“服務器”運行在用戶態,等待客戶提出服務請求。“客戶”,可以是另一個操作系統的組件,也可以是應用程序,它通過發送一個消息給服務器來請求服務。運行在核心態的操作系統的微內核把該消息傳遞給服務器,該服務器執行操作,內核用另一種消息把結果返回用戶。
Windows2000融合了分層操作系統和客戶服務器微內核操作系統的特點。對性能影響很大的操作系統組件在核心態下運行。在核心態下,組件可以和硬件交互,也可以在組件之間交互,并且不會引起描述表切換和模式轉變,例如,內存管理器、高速緩存管理器、對象及安全性管理器網絡協議、文件系統(包括網絡服務器和重定向程序)、所有線程和進程管理都運行的核心態。
當然,所有這些組件都應該受到保護,以避免給其它的應用程序侵擾,應用程序不能直接訪問操作系統特性部分的代碼和數據(盡管他們可以快速調用其它的內核服務)。這種保護使得Windows2000成為既堅固又穩定的應用程序服務器的原因之一。而且從核心操作系統服務的角度,如虛擬內存管理、文件操作、復合文件及打印共享來看,Windows2000作為工作站平臺仍是迅速和敏捷的。
由于WDM驅動程序的標準應用平臺是Windows 2000,是內核的重要組件之一并和其它內核組件有相當多的關聯,為本文討論的完整性,首先討論Windows 2000的系統結構。
1.2 Windows 2000的系統結構
用戶態代碼模式主要包括各個環境子系統:POSIX,OS/2,Win32。在這三個子系統中Win32比較特殊,它是Windows 2000的必須組件。實際上,其它兩個子系統只是在需要時才被配置啟動,而Win32必須始終處于運行狀態。
A) 硬件抽象層(HAL) HAL是一薄層軟件,它是硬件與操作系統其它部分的接口,是物理硬件資源的一種抽象。我們可以稱之為“抽象硬件模型”。HAL通過動態鏈接庫(DLL,Dynamic Link Library)實現,管理的項目包括:
w 片外高速緩存
w 定時器
w I/O總線
w 設備寄存器
w 中斷控制器
w DMA控制器
各種系統組件使用HAL函數與CPU外的硬件打交道,這樣就把平臺特定的細節對系統的其余部分隱藏起來,可移植性。特別地,HAL例程的使用使得內核和設備驅動程序在有相同CPU體系結構的平臺上二進制代碼兼容。
B) 內核(Kernel) 內核是整個操作系統的神經中樞,同執行體的其它部分不同,內核的大小從不會溢出內存。盡管執行一個中斷服務例程可以中斷內核,但內核的執行操作永遠不會被其它正在運行的線程搶先。內核始終運行于核心態,其代碼短小精悍,可移植性優異。內核主要由C語言編寫,對那些需要盡可能快速執行的代碼或非常依賴于處理器性能的任務保留用匯編語言編寫。它提供管理以下功能的機制:
w 中斷和異常處理
w 線程調度和同步
w 多處理機同步
w 定時控制
w 內核對象
內核的目標之一是提供一個嚴格定義的,可預測的操作系統基本要素和機制的低級操作。內核通過執行操作系統機制和避免制定策略而使其自身和執行體的其它部分分開。其主要通過提供兩類對象來為其它部分服務:
w 調度者對象 負責同步性能并改變或影響線程調度。
w 控制對象 這些對象以某種方式控制操作系統的行為。
例如:設備驅動程序將使用的系統線程屬于調度者對象,推遲過程調用、中斷對象屬于控制對象。
C) 執行體(Executive) 圖1中的暗紋部分都屬于執行體,但它們是完全獨立的,只通過很好定義的接口來通訊。
1)系統服務接口
提供用戶模式到內核模式的受控路徑。在Win2000中,系統服務調度者使用一種基于CPU硬件異常機制的技術給用戶模式代碼提供對Executive服務的訪問權。
2)對象管理器
執行體通過一個基于對象的接口給用戶模式進程提供服務。文件、進程、線程、內存段等事物都是對象。對象管理器執行管理執行體對象的所有工作,包括創建和刪除對象、維護全局對象名字空間,以及記錄對指定對象有多少等待的引用。
3)配置管理器
從驅動程序開發者的角度看,配置管理器的主要工作是,使用登記(Registry)數據庫,維持安裝在機器上的所有硬件和軟件資源。
驅動程序使用Registry作以下工作:
w 把自己標識為可信任的系統組件
w 查找和分配外圍硬件
w 建立錯誤記錄日志文件
w 啟用驅動程序性能測量
4)進程管理器
進程是Windows2000中資源記錄和安全性檢查的單位。每個進程都有自己的虛擬地址空間和安全性標識。一個進程中包含一個或多個線程(Thread)。進程管理器處理進程和線程的創建、管理和銷毀,它還為同步線程的活動提供一組標準的服務。
5)安全引用監視器
該組件強制系統的安全性策略。安全性引用監視器提供一組原語,其它組件可以調用它們來驗證對對象的訪問,檢查用戶特權和生成審查消息。驅動程序一般不與它打交道,I/O管理器在調用驅動程序中的任何例程之前處理這類工作。
6)虛擬內存管理器
在Windows2000下,每個進程有一個4GB的虛擬地址空間。這個空間的0~2GB是進程的私有代碼和數據、堆棧和堆空間。它還含有進程使用的任何文件映射(File Mapping)對象和DLL。2~4GB只包含內核模式代碼。虛擬內存管理器的任務之一是,使用按需分頁的虛擬內存管理技術來維護地址空間映像。從驅動程序開發者的觀點來看,它負責維護系統的堆空間。在DMA操作中,它還為驅動程序構造和操作緩沖區。
7)局部過程調用(LPC)
局部過程調用是一個消息傳遞機制,用于在同一臺機器上的進程之間通信。LPC主要由受保護的子系統及其客戶程序使用,設備驅動程序對LPC機制沒有訪問權。
8)I/O管理器
執行器組件把I/O請求從用戶模式和內核模式線程轉換成對各種驅動程序例程的合適順序的調用。通過使用很好定義的接口,I/O管理器能夠以相同的方式與所有驅動程序通信。
9)PnP管理器
PnP管理器由兩部分組成:核心態PnP管理器和用戶態PnP管理器。核心態PnP管理器同操作系統組件和內核驅動程序進行交互來動態的維護、配置、管理設備。用戶態PnP管理器和用戶安裝組件進行交互,來配置和安裝設備。用戶態PnP管理器同時也和應用程序交互,例如:為一個應用注冊一個設備變化通知消息用來在設備狀態發生變化時通知應用程序。
10)Power管理器
Power管理器負責管理系統的電源使用。它負責維護一個系統范圍內的電源策略,并負責Power IRP在系統中傳遞路徑。Power管理器通過以下幾點來考慮系統應處于什么狀態――淺度睡眠,深度睡眠,關閉,還是正常運作 :
w 系統當前活動狀況
w 系統電池狀態
w 應用程序的電源請求
w 用戶動作,例如:按下電源啟動按鈕
w 控制面板的設置
1.3 Windows 2000和WDM 驅動程序的設計目標
WDM設備驅動程序和Windows2000在設計目標上有很多方面是一致,尤其是系統輸入輸出管理器更是如此。這些目標包括以下幾方面:
A) 的可移植性
Windows2000用以下幾種方法實現在不同的硬件結構和平臺上的可移植性:
w 大多數的Windows2000組件提供一組內核服務例程, 供驅動程序和其它內核組件調用。 這些服務例程提供統一的編程接口,盡管這些服務例程底層的實現因為Windows版本不同而不同,而他們的編程接口保持穩定不變,這就使得基于其上的組件和驅動程序保持平臺無關性和向后兼容性。
w Windows2000采用了分層設計,依賴于處理機體系結構和平臺的系統底層部分被隔離的單獨模塊之中,所以系統的高層可以被屏蔽在千差萬別硬件平臺之外。提供操作系統可移植性的兩個關鍵組件是HAL和內核。依賴于體系結構的功能(如線程描述表的切換)在內核中實現。在相同體系結構中,與計算機硬件交互的功能在HAL中實現。
w Windows 2000主要是用可移植C語言編寫――操作系統執行體、實用程序、設備驅動程序使用C語言編寫,圖形子系統部份和用戶界面是用C++語言編寫。只有那些必須和系統硬件通信的操作系統部分(如中斷處理程序),和性能極度敏感(如描述表切換)的部分使用匯編語言編寫。匯編語言代碼不僅存在于內核及HAL之中,而且存在于執行體中的少量區域(例如實現執行體里本地過程調用機構中的一個模塊),甚至存在在一些用戶態代碼庫中。多數Windows2000組件是用C語言編寫,所以這個操作系統就容易在復雜指令CPU平臺和精簡指令計算機CPU的平臺上移植。內核設備驅動程序也應當用C語言編寫,這樣它也可以在系統兼容的編譯器上重新編譯鏈接直接生成不同平臺的設備驅動程序。WDM驅動程序同時可以在Windows98以后的系列操作系統中保持兼容,而不用重新編寫代碼。
w 為保證系統的可移植性,驅動程序應避免使用平臺相關的C編譯器進行編譯。大體上講,驅動程序的代碼盡可能用標準C編寫的.驅動程序應注意以下幾點:
1) 驅動程序代碼應避免使用平臺相關的數據結構
2) 避免調用任何保持狀態的C運行時庫函數
3) 應盡量使用操作系統提供的服務例程同時盡量少的使用C運行時庫函數
4) 不能在驅動程序中使用浮點運算
B) 軟硬件可配置性
w 避免使用機器相關的硬編碼,使得同一硬件可以在其它不同配置的機器上運行,這叫做硬件可配置性。
w 底層的驅動程序要為上層的各種驅動程序服務,它不能武斷地猜測上層驅動的性質和特定實現,這叫做軟件可配置性。
w Windows 2000的配置管理器提供了注冊登記(Registry)數據庫,在其中存儲了系統的硬件、各種外設及其驅動程序的信息。驅動程序可以從中得到機器的硬件配置和系統中的其它驅動信息。即插即用管理器和內核驅動程序利用注冊數據庫來取得本機上硬件以及其它驅動程序的配置。Win2000驅動程序也把自己的設備信息以及機器相關的配置信息儲存于此。
C) 總是可以被剝奪執行權,總是可以被中斷
在Windows2000中內核組件代碼按照以下優先級原則進行運行:
w 內核定義的線程優先級策略
系統中各線程都有其自身的優先級屬性。大體上講兒,大多數系統線程都有可變的優先級屬性,它們總是可以被剝奪的而且它們和其它優先級相同線程一起被調度。一些系統中的線程具有實時優先級,它們可以搶先其它低優先級線程運行,同時它們也被優先級更高的線程搶先。
w 內核定義的中斷請求級策略
內核同時把不同的軟件中斷和硬件中斷賦予不同的優先級,這樣某些高優先級的內核代碼就能夠運行在較高的中斷請求級,某些特定的實時代碼就能擁有很高的調度優先權。通過內核代碼中運行的中斷請求級可以確定相應的硬件優先級。內核模式代碼應該始終可以被中斷,較高優先級的中斷隨時都有可能發生,它可以中斷當前執行的代碼,立即投入運行。換句話說,在一定中斷請求級上運行的代碼在當前處理器上可以屏蔽相同或較低優先級的中斷。內核定義了一種可移植的IRQL,如果處理器具有特殊的中斷相關的特性(例如,第二時鐘),則可以增加IRQL。按優先級排隊中斷,較高優先級的中斷可以搶先較低優先級的中斷服務,每個處理器IRQL設置決定了處理機可以接受哪些中斷,IRQL也被用于同步訪問核心態數據結構,當核心態線程運行時,它可以降低或提高處理器的IRQL。如果中斷源的IRQL高于當前中斷設置,則它的中斷可以中斷處理器;如果中斷源的IRQL等于或低于當前中斷級,則它的中斷將被封鎖或屏蔽,直到一個正在執行的線程降低了IRQL。
操作系統的可以被剝奪和可以被中斷的設計目標帶來的好處是限度提高平均性能,任何中斷服務例程都可以被更高中斷請求級的中斷服務例程中斷,任何線程都可以被更高優先級的線程搶先。
D) 多處理器安全
在Windows2000多CPU操作系統平臺,以下幾種情況有可能發生:
在對稱多處理多平臺上,每個處理機都可以訪問內存,發生中斷,訪問輸入輸出控制寄存器。(比較而言,在非對稱多處理平臺上,只有主CPU可以處理中斷。)
Windows2000被設計為可以不加修改地運行在單處理器和多處理器平臺上,所有驅動程序也必須安全的實現多處理器安全,避免被一個處理機訪問和修改的存儲器同時被另一臺處理器訪問和改變,比如說,一個設備的中斷同時在兩個處理器上發生,那么在一個處理器上特定優先級上的中斷服務例程必須提供某種機制排他的訪問臨界區。在多處理器情況下,驅動程序的輸入和輸出請求可能是重疊的,這就是說,一臺處理機正在處理輸入請求,而另一個處理器在和設備通信,在這種情況下,所有的驅動程序必須同步對共享的資源進行訪問(如果有必要的話)。內核組件提供一種叫自旋鎖的機制,用來在多處理機平臺上保護共享數據,使用自旋鎖有以下兩條原則:
w 在一個時刻只有一個例程能夠獲得此自旋鎖,只有持有它的例程可以訪問被自旋鎖保護數據,其它例程必須等待這個例程是釋放自旋鎖,然后重新獲得后,才能去接觸共享的數據。
w 每一個系統中的自旋鎖都有相關的中斷請求級,只有運行在這個中斷請求級上的例程才有可能獲得自旋鎖。
E) 基于面向對象的設計的思想
w Windows2000是基于面向對象的思想設計,執行體中的不同組件定義了許多對象類型,每一個組件同時提供了操縱這些對象方法,組件不允許直接操作其它組件的對象,為使用其它組件的對象,必須使用其提供的接口。嚴格遵循這些原則有利于增強Windows2000的可移植性和靈活性,例如,未來版本的Windows操作系統有可能部分或者全部的重新定義這些對象結構,這些被重寫的對象版本將不會對現有的執行體組件產生影響,換句話說,操作系統中組件的通信服務方式也是基于接口,驅動程序同樣應該避免使用引用或者指針操作對象本身。
w 和操作系統一樣,驅動程序和他們的設備也是基于面向對象對象設計的,對系統的其它組件而言(包括用戶代碼),同設備聯系被定義為一種打開文件操作,在輸入輸出子系統中,每一個驅動程序(邏輯,虛擬,和物理設備)都由“設備對象”來表示,每一個驅動程序加載映像都用“驅動對象”表示。輸入輸出管理器定義這些對象。
F) 依可重用的包(輸入輸出請求包,IRP,I/O Request Packet)驅動的I/O
輸入輸出管理器的主要任務是接收輸出請求(通常來自于用戶應用程序),創建IRP來代表它,將這些IRP引導到正確的服務例程來處理;并且跟蹤他們直到他們被完成,向發起者返回狀態參數。輸入輸出管理器,插即用管理器,電源管理器使用IRP來同核心態驅動程序進行通信,并且允許驅動程序之間進行通信。因此每一個IRP都由兩大部成:
w 固定部分:輸出輸入管理器用來保持原始輸入請求信息,例如調用者線程ID和調用參數,打開文件指定的設備對象,等等。固定部分同時包含一個輸入輸出狀態,驅動程序用于返回輸入輸出操作的結果。
w 可變部分:數量不同的輸入輸出堆棧,用于支持分層的驅動程序結構。
G) 支持異步I/O
w I/O管理器提供異步I/O支持以便I/O傳輸的發起者可以不必等待I/O操作的完成而繼續它的工作。異步I/O提高了用戶應用的性能,也提高了驅動程序的性能。異步I/O使得驅動程序不必按照I/O請求到來的順序進行操作。這樣,驅動程序內部必須維護I/O請求當前處理的階段狀態。
w 內核驅動程序處理I/O請求的次序不一定和這些I/O請求到達I/O管理器的次序相同。I/O管理器或高層驅動也可以將大的數據請求塊劃分為多個小塊來進行處理。而且,內核驅動并不一定串行的處理這些I/O請求。這就是說,驅動程序不一定等到前一個IRP完成才去處理下一個IRP。
2 WDM驅動程序和I/O子系統的協同工作機制分析
在Windows驅動程序模型(WDM)出現之前Microsoft為它的兩個系列操作系統提供了不同的驅動程序模型,他們分別是:Windows3.1和Windows95的Vxd以及NT式的驅動程序。兩種驅動程序的架構是如此的不同,以至于程序員必須為每個設備在兩種系統上分別編寫、編譯、調試驅動代碼,這對于程序員來說是一個很大的負擔。
為統一驅動程序架構,減輕程序員的負擔,微軟推出了新型的WDM驅動程序模型,現在的Windows 98(第二版)以及Windows 2000均采用了這個模型。而且微軟已經宣布未來的Windows系列操作系統的驅動模型將是基于WDM構架的。
Windows驅動程序模型(WDM)的設計思想是非常先進的,它迎合了當前的操作系統的設計的先進之處:
w 它是支持多處理器架構的,完全支持對稱多處理
w 它是處理器無關的,支持多種處理器架構。
w 它完全支持即插即用和電源管理
盡管對于用戶來說Windows 98 and Windows 2000下的模型是相同的,但是他們的工作機制是完全不同的,以下將分別討論。
2.1 Windows2000下的WDM驅動程序和I/O子系統的協同工作機制分析
Windows 2000是分態的操作系統,因此在系統中代碼運行在兩種模式下:用戶態和核心態。用戶應用程序運行在用戶態,操作系統代碼(如系統服務和設備驅動程序)在核心態下運行。在核心態處理器模式中,代碼可以訪問所有系統內存和所有的CPU指令。操作系統軟件的特權級別高于應用程序軟件,通過這種機制,使得應用程序的不當行為在總體上不會破壞系統的穩定性。Windows 2000對核心態運行的組件不提供任何保護。換句話說,一旦處于核心態,系統代碼就可以完全訪問系統內存空間,并在訪問時不受安全性的約束。
Win32 應用程序運行在用戶態,操作系統嚴格限制應用程序的行為,防止其對其它應用和系統代碼的破壞。因此用戶態程序只能調用Win32子系統提供的API來同設備交互,Win32子系統模塊中的服務代碼然后調用平臺無關的系統服務例程來切入核心態并調用核心態組件(I/O管理器)提供的服務例程。當請求傳遞到I/O管理器時,它創建一個IRP(I/O Request Packet)并將其傳遞到適當的驅動程序去,并給應用程序一個消息,通知這次I/O操作還沒完成。應用程序收到通知后或者繼續執行,或者掛起等待。在任何一種情況下驅動程序獨立的執行來服務應用程序。
驅動程序終需要訪問硬件來完成I/O請求,在程序控制的I/O方式下的讀請求,驅動程序的動作為讀I/O端口或寄存器。盡管驅動程序運行在核心態下,可以直接和硬件交互,但在大多數情況下,為保持其可移植性,驅動程序一般調用硬件抽象層提供的例程來和硬件交互。硬件抽象層提供一種與處理器平臺無關的方法來執行實際的I/O 操作。例如,在Intel x86處理器平臺上,硬件抽象層使用IN指令,在Alpha平臺上,它將使用MEMORY讀取操作。
驅動程序完成I/O操作后,它將調用一個特殊的內核服務例程來完成IRP。這時,因這個I/O請求掛起的任何Win32應用將繼續執行。
2.2 Windows 98下的WDM驅動程序和I/O子系統的協同工作機制分析
在Windows98中,操作系統內核被稱為虛擬機管理器(VMM),因為它的主要任務是在單一的物理硬件上創建一個或多個“虛擬”的機器來共享這些硬件。而虛擬設備驅動程序(VxD)的設計初衷也是虛擬一個特定的硬件來輔助虛擬機管理器產生一種假象,那就是:每一個虛擬機都擁有一套完整的硬件。這種設計源于Windows 3.0,并在Windows 95和Windows 98中沿用。
Windows98并不象Windows 2000那樣統一有序的處理I/O請求。Windows98在處理磁盤、串口、鍵盤等等這些不同的設備時采用的機制有很大不同。并且如圖3所示,Windows98在處理32位和16位應用的I/O請求時,采用的方法也是根本不同的。圖3中的左列展示了系統是如何處理32位應用的I/O請求的。在Windows98中,對于不同的設備,應用程序采用不同的機制來和驅動程序進行交互。應用程序可能調用一個Win32 API例如ReadFile來讀設備,但這些設備僅包括磁盤文件,串口,和一些由WDM驅動程序驅動的設備。但對于其它設備,應用程序只能通過基于DeviceIoControl的一些特別的機制來和設備通訊。即使是同樣調用ReadFile,應用程序使用一種機制來和磁盤驅動交互,采用另一種機制和串口驅動通訊。而由WDM驅動的設備的I/O請求方法和前兩種又有本質的不同。
圖3的中列和右列展示了系統是如何處理16位(Windows 3.1)和DOS應用程序的I/O請求的。在兩種情況下,應用程序都直接或間接的和用戶態驅動程序進行交互,用戶態驅動程序將請求傳遞到核心態虛擬設備驅動,再由核心態虛擬設備驅動代理應用程序和硬件直接交互。
雖然在Windows 2000中以一種統一的方式(IRP)在內核中傳遞I/O操作,但在Windows 98中,即使在核心態也沒有統一方法的來代表I/O請求。
但對于WDM驅動程序來說,Windows 98在處理方式上通過一個系統模塊(NTKERN.VXD)來模仿Windwos 2000內核的處理方法。這個模塊提供了Windows 2000內核的大部分服務例程的仿真,并模擬I/O管理器來產生和發送IRP。WDM驅動程序幾乎無法區分兩種平臺的差異。
3 分層的設備驅動程序和即插即用設備棧
3.1 分層的設備驅動程序
圖4說明用戶的動作如何由設備驅動程序處理。應用程序對設備I/O進行Win32調用,這個調用由I/O系統接收。I/O 管理器發送IRP來請求驅動程序的處理。
在簡單的情況下,I/O管理器只是把IRP傳遞給一個設備驅動程序,這個設備驅動程序和硬件交互,并完成IRP的處理。I/O管理器把數據和結果返回給Win32和用戶應用程序。
通常IRP由分層的驅動程序棧來處理。高層的驅動程序把請求劃分成更簡單的請求并傳遞給下層驅動程序。例如,在文件系統驅動程序中,層的驅動程序知道文件如何在磁盤上表示,但不知道如何得到數據的細節。中間層次的驅動程序進一步處理請求,將一個IRP中的請求劃分為若干個小的請求并傳給下層驅動程序。,層的驅動程序與硬件打交道。
在任何地的地方,驅動程序被設計為盡可能的通用。例如,SCSI端口知道如何把磁盤數據請求轉換成SCSI請求,但是,它再向SCSI小端口驅動程序發出SCSI請求,這些小端口驅動程序知道如何訪問各種SCSI硬件。
過濾驅動程序是一種中間驅動程序,它位于其它的驅動程序層次之間,提供一些附加的功能,而不影響其它驅動程序。例如,過濾驅動程序可以用以提供容錯的磁盤訪問,在這個驅動程序中,數據被寫到兩個不同的物理磁盤,保證數據的冗余保存。
圖4 驅動程序分層簡化模型
3.2 即插即用設備棧
Windows驅動程序模型重新定義驅動程序分層,以適用于即插即用系統。一個設備棧代表處理請求的驅動程序層次,如圖5所示??偩€驅動程序控制對總線上的所有設備的訪問。例如,如果訪問USB設備,必須使用USB總線驅動程序。
總線驅動程序負責枚舉它的總線,這意味著發現總線上的全部設備和檢測設備何時被添加或刪除??偩€驅動程序創建一個物理設備對象來代表它發現的設備。一些總線驅動程序簡單的控制對總線的訪問,一旦有了控制權,就可以對總線做任何想要的工作。在其它情況下,總線驅動程序為我們處理總線上的所有事務。
功能驅動程序知道如何控制設備的主要功能,它分層在總線驅動程序的上面。功能驅動程序創建一個功能設備對象,放在設備棧中,在USB的情況下,功能驅動程序必須使用USB類驅動程序訪問它的設備。但是,在其余情況下,一旦總線驅動程序接管,功能驅動程序可以直接訪問硬件。有多個功能驅動程序分層在個功能驅動程序之上是非??赡艿?。
各種類型的過濾驅動程序可以插在設備棧中。對總線上的所有設備,總線過濾驅動程序被加在總線驅動程序之上;而對于特定類的所有功能驅動程序,添加類過濾驅動程序。設備過濾驅動程序僅對特定的設備添加。上層的過濾驅動程序在功能驅動程序之上,而底層過濾驅動程序在功能驅動程序之下。
用戶的請求總是在設備棧的頂部進入。假設用戶程序標志了一個它想訪問的功能設備,I/O管理器保證它的全部請求都發送到設備棧的頂部,這樣任何高層的過濾驅動程序或功能驅動程序首先得到處理這些請求的機會。
3.3 標準總線驅動程序和類驅動程序
圖6給出了Windows提供的主要類驅動程序和總線驅動程序,它們是作為總線驅動程序和功能驅動程序執行的通用驅動程序。在大多數情況下,主系統驅動程序和與硬件接口的另一個驅動程序或另一類驅動程序一起使用。這些輔助驅動程序通常成為小驅動程序。
配置和電源接口(ACPI)總線驅動程序與PC ACPI BIOS打交道,枚舉系統中的設備并控制它們的功率使用。PCI總線驅動程序枚舉和配置PCI總線上的設備。PnPISA總線驅動程序對可以使用即插即用配置的ISA設備作類似的工組。
流類驅動程序提供訪問高帶寬,時間關鍵和視頻,音頻數據的基礎。
IEEE 1394枚舉和控制IEEE 1394高速總線,這個總線驅動程序使用端口驅動程序訪問IEEE 1394控制電路。IEEE 1394客戶驅動程序發出IEEE 1394請求塊來控制它們的設備。
USB枚舉和控制低速的USB總線。主機控制器驅動程序作為訪問主要的兩類USB主機控制器的標準。
SCSI和CDROM驅動程序用于訪問硬盤,軟盤,光盤和DVD。
人工輸入設備類設備驅動程序提供輸入設備的一個抽象視圖。
4 WDM驅動程序的結構及主要例程
WDM驅動程序的主要工作如下:
w 初始化自己。
w 創建和刪除設備。
w 處理Win32打開和關閉文件句柄的請求。
w 串行化對設備的訪問。
w 訪問硬件。
w 調用其它驅動程序。
w 取消I/O請求。
w 超時I/O請求。
w 處理一個可熱插拔的設備被加入或刪除的情況。
w 處理電源管理請求。
以下分別分析了完成以上功能的WDM驅動程序模塊和工作原理:
A) WDM驅動程序入口點和回調例程
WDM驅動程序有兩個主要的初始化入口點---- DrvierEntry和AddDevice例程。DrvierEntry注冊其它回調例程的。在運行過程中,內核會調用不同的回調例程來完成不同的任務。
下表列出了主要的回調例程:
DriverEntry 初始驅動程序入口點,設置主要的回調例程。
AddDevice 一個新的即插即用設備(PnP)被添加。
I/O請求包處理例程 被調用用來處理希望處理的IRP
Unload 卸載驅動程序
StartIo 串行處理IRP的回調例程
ISR 中斷服務例程
DpcForIsr 延時過程調用例程,完成一個I/O請求和開始另一個中斷驅動的傳輸
臨界斷例程 同步一個處理器上的中斷執行。由低級IRQL的任務調用來與硬件交互
Cancel 取消一個IRP
Completion 當一個低層驅動程序完成一個IRP的處理時被調用,這允許當前的驅動程序作更多的工作
AdapterControl 當一個DMA通道適配器可用時調用
ControllerControl 當一個控制器空閑時調用
Timer 定時器回調例程
CustomerTimerDpc TimerDpc的回調例程
CustomerDpc 通常用于處理工作隊列
即插即用通知 當設備PnP狀態發生變化時被調用
電源通知 當設備Power狀態發生變化時被調用
ConfigCallBack 查詢設備硬件描述回調
B) I/O系統服務派發(Dispatch)例程
驅動程序的DriverEntry例程必須設置一系列的回調例程來處理IRP。下表列出了常見的Win32設備I/O函數和它們對應的IRP:
CreateFile “Create” IRP
CloseHandle “Close” IRP
ReadFile “Read” IRP
WriteFile “Write” IRP
DeviceIoControl “IOCTL” IRP
內部的IOCTL IRP
“Create”, “Close”, “Read”, “Write”, “IOCTL”和內部的IOCTL的處理程序通常稱為分發例程,因為它們通常僅執行IRP的一些初始化處理,如檢查所有的參數是否合法,然后把IRP分發到驅動程序的其它地方去處理。IRP通常需要串行處理,使得驅動程序以一種安全的方式與硬件打交道。
5 WDM驅動程序的工作流程分析
A) 創建設備
設備的創建一般在即插即用管理器發現設備時進行。類似的,在執行過程中,當驅動程序卸載或者PnP管理器告訴設備正在被刪除時,我們要刪除這些設備對象。
大多數的WDM設備對象都是在PnP管理器調用AddDevice入口點時創建的。這個例程在插入新設備和安裝INF文件指示這個驅動程序是要運行的驅動程序時被調用。在此之后,一系列的PnP IRP被發送到驅動程序,指示設備應當何時啟動和查詢它的功能。,一個刪除設備PnP IRP指示設備已經被刪除,所以驅動程序刪除設備對象。
NT式驅動程序在它們想創建設備的時候創建設備。它們的DriverEntry例程通常尋找自己的硬件,找到后創建設備對象。
在創建設備后,為了使Win32可見,我們必須為每個設備創建符號鏈接。可以采用兩種方法創建符號鏈接:種方法是采用顯示的“硬編碼”符號鏈接名,
用戶態程序必須類似的把設備名硬編碼到源代碼中。另外一種方法是使用設備接口,每個設備接口由一個全局標志符標志。把設備注冊為一個特定的設備接口就創建了一個符號鏈接。用戶態設備可以取得擁有此GUID的設備。
B) 硬件資源分配
低層的驅動程序需要知道為他們分配了哪些硬件資源。常見的硬件資源是I/O端口,存儲器地址,中斷和DMA線。
處理PnP IRP的WDM驅動程序在收到“啟動設備”的PnP IRP時被告知設備的資源。NT式的驅動程序必須自己發現資源并請求使用這些資源。
C) 驅動程序的分層調用
WDM驅動程序花大量的時間訪問其它驅動程序。一個即插即用設備是在一個設備對象棧中,把IRP沿設備棧傳遞到下一個驅動程序是很常見的。
一些類型的IRP(如即插即用,電源管理等)常常立即傳遞到設備棧中的下一個設備。
在另一些情況下,驅動程序的工作是通過調用設備棧中的下一個設備實現的。例如,USB客戶驅動程序通常通過沿設備棧向下傳遞IRP來調用USB總線驅動程序。
D) 串行化處理
訪問硬件的任何設備必須使用某種機制保證驅動程序的不同部分不同時訪問相同的硬件。在一個多處理器系統中,“Write”IRP處理程序可以同時在兩個不同的處理器上運行。如果它們兩個都試圖訪問相同的硬件,則會出現不可預料的結果。同樣,如果一個“Write”IRP正在試圖訪問硬件的同時發生了中斷,那么,兩個動作可能會相互影響。
內核采用兩種機制來同步這些沖突操作:
w 種是采用臨界段例程,使用這些臨界段例程保證代碼不會被中斷處理程序中斷。這些臨階段例程在內部使用了中斷自旋鎖,所以可以保證多處理器同步。
w 第二種是使用StartIo例程串行處理IRP,每個設備對象有一內部的IRP隊列,驅動程序的派發例程將IRP插入這個隊列中。內核I/O管理器從這個隊列一個個的取出IRP,并把它們傳遞到驅動程序的StartIo例程。所以StartIo例程串行的處理IRP,保證不與其它的IRP處理例程沖突。
如果一個IRP已經在一個隊列中,此時用戶線程突然中止或其調用Win32函數取消了這次I/O,驅動程序必須取消這個IRP。這可以通過給每一個排隊的IRP掛接一個取消回調例程來實現。
如果用戶態程序關閉了設備的文件句柄,而這個設備有重疊請求在等待,則必須要有“清理”例程。清理例程負責取消與一個文件句柄關聯的所有IRP。
E) 訪問硬件
在取得了I/O端口和內存地址后,訪問硬件就顯得比較直接,但是由于Windows 是多任務系統,在一般情況下占用處理器的時間應小于50微秒,需要長時間的硬件訪問應采用系統線程的方法。
因為中斷服務例程的IRQL(中斷請求級)很高,故在中斷服務例程中應盡量減少訪問硬件時間,而且很多內核例程在這個中斷請求級上被禁止調用,故一些中斷善后工作在延遲過程調用(DPC)中實現。
F) 即插即用支持技術
即插即用(PnP)是計算機系統自動識別和適應硬件配置的改變的技術,完全的即插即用不僅需要硬件的支持,同時也需要軟件的支持。對用戶來說,他可以自由的向計算機中添加和刪除設備,而無需使用笨拙的手工配置同時不必深入了解復雜的計算機軟硬件知識。
即插即用需要設備硬件,系統軟件,和驅動程序的支持。PnP的發起者定義了關于易識別設備和基本系統組件的PnP工業標準。這些標準主要闡述了系統軟件和驅動程序如何支持即插即用。
系統軟件和驅動程序對即插即用的支持主要提供以下功能:
w 自動識別已安裝的設備
w 硬件資源的動態重分配
w 自動加載正確的驅動程序
w 提供使得在硬件環境發生變化時,驅動程序和用戶模式代碼得到通知的機制
PnP驅動程序是對PnP支持很重要的部分。PnP驅動程序必須提供PnP調用入口,處理繁多的PnP IRPs,并且遵循PnP的設計規范。
圖7說明了操作系統的組件如何同WDM驅動程序一起提供即插即用的支持。從圖7可以看出PnP管理器由兩部分組成:核心態PnP管理器和用戶態PnP管理器。核心態PnP管理器負責同操作系統組件和WDM驅動程序交互來配置、管理和維護設備。用戶態PnP管理器主要和用戶態安裝程序一起來簡化設備的安裝工作。同時,PnP管理器只有和WDM驅動程序緊密合作,才能使得系統對即插即用有完整的支持。WDM驅動程序遵循Windows 驅動模型規范并且可以不加修改的同時運行在Windows2000 和Windows98中。為支持PnP,WDM驅動程序的設計必須遵守以下原則:
w WDM驅動程序必須遵循以設備為中心的即插即用驅動程序模型。PnP管理器在全局的基礎上管理系統的設備,并調用驅動程序來服務它們的設備。當PnP管理器發現設備時,驅動程序的AddDevice例程將被PnP管理器調用來服務這個設備。
w WDM驅動程序必須遵守PnP軟件設計原則例如:驅動程序必須擁有專門的例程來處理繁多PnP IRP并正確傳遞這些PnP IRP,這是一項非常繁瑣復雜的工作。
w WDM驅動程序不應自已聲明硬件資源,此項工作應由PnP管理器在系統范圍公斷并調整資源后完成。
w WDM驅動程序應該是模塊化的,驅動程序的各個例程都要求有獨立的入口和模塊以方便PnP管理器在需要時調用。
為配合PnP管理器的工作,WDM驅動程序必須自己維護多個PnP狀態。在PnP系統中,當設備被配置、啟動、停止時設備會在不同的PnP狀態之間轉換,如圖8所示。
正確的維護本設備的PnP狀態和響應相應的PnP IRP的狀態遷移指示是WDM驅動程序對PnP支持的關鍵。
G) 電源管理支持技術
電源管理是在系統范圍內的有效使用電源的綜合方法。擁有硬軟件電源管理支持的計算機系統能夠擁有以下功能:
w 短的啟動和關機延遲。
w 極大提高的整體電源使用效率和更長的電池壽命。
w 更安靜的操作。
在Windows2000和Windows98以及其它支持電源管理的操作系統中,計算機和它的外設被維持在可能的電源使用水平上來完成它們當前的工作。WDM驅動程序和操作系統合作來管理它們的設備電源。如果所有的驅動程序都支持電源管理,那么操作系統就可以在全局的基礎上維持系統的電源消耗,來節約電量的使用,更快的啟動和關機,而且可以隨時被從睡眠中喚醒。
支持PnP的驅動程序必須支持電源管理,反之亦然。電源管理和即插即用是綜合在一起的且是相互依賴的。
電源管理在兩個層次上工作,層在獨立的WDM驅動程序中,第二層在以電源管理器為核心的系統整體范圍內。
電源管理器作為操作系統內核的一部分在系統范圍內管理電源水平。所有的驅動程序都支持電源管理,電源管理器就可以在系統范圍內統一管理電源的消耗,不僅使系統在適當的時候進入完全開啟和完全關閉狀態,而且可以在幾個不同的中間狀態中進行睡眠。
設備電源管理應用于單獨的設備。支持電源管理的驅動程序可以將它的設備在使用時加電,并且在不用時掉電。如果硬件支持,則設備可以在驅動程序的控制下進入中間的設備電源狀態。
電源管理和即插即用一樣同樣需要硬件,系統軟件和驅動程序的共同支持。硬件的支持在“配置與電源管理接口規范”(ACPI 參考http://www.teleport.com/~acpi2))中有詳細說明。WDM驅動程序和電源管理器從軟件上維護設備及系統的電源狀態。圖9說明了WDM驅動程序如何和電源管理器合作進行電源管理的。
用戶可以通過控制面板和系統API來向電源管理器輸入他們的電源命令。電源管理器管理系統范圍內的電源策略----支配系統電源使用的規則。通過從控制面板和系統API得到信息,電源管理器可以決定應用程序正在或者可能需要使用不同的設備,從而適當的調整系統的電源策略。
當電源管理器請求改變系統電源狀態時,驅動程序應當響應請求并把它們的設備投入到對應的設備電源狀態。
電源狀態指明了電源消耗的水平。電源管理器設置系統電源狀態,驅動程序設置設備電源狀態。WDM驅動程序定義了同ACPI說明相同的五種系統的電源狀態(從S0到S5)和四種設備電源狀態(從D0到D5)。同即插即用的支持相同,正確的維護本設備的電源狀態和響應相應的Power IRP的電源狀態遷移指示是WDM驅動程序對電源管理支持的關鍵。
6 小結
WDM設備驅動程序工作在Windows2000或Windows98的內核狀態,和系統的其它核心部件打交道。理解Windows2000的設計目標、實現及其結構對編制合格的驅動程序至關重要。
本文首先介紹了Windows2000操作系統的設計目標、特點,同時著重介紹了內核模式的組成和各構件的功能。作為系統重要組成部分的WDM驅動程序在很多方面和操作系統的設計目標是一致的。本文第二節簡要地介紹了WDM驅動程序的分類以及驅動程序的特點、設計目標。由于WDM驅動程序工作在Windows2000和Windows98下時和I/O子系統的交互的差異(由于操作系統設計的差別),本文分別討論了WDM驅動程序在不同操作系統下的工作模式。指出了它們的異同點。WDM驅動程序的即插即用設備棧和標準總線驅動程序也是本文討論的內容之一。在本文的,本文給出了WDM驅動程序的結構和主要例程,并分析了WDM驅動程序的工作原理。
從本文中可以看出,要編制WDM設備驅動程序必須掌握大量的預備知識,理解和領會各種復雜的內核例程和許多繁雜的驅動程序開發原則,這就帶來了本文開始時討論過的弊病:需要專門的人力投入,開發周期長,正確性、可靠性難以保證,升級困難,可讀性差等。
如何更高層次上利用DDK,實現通用部分的封裝(如資源查找和分配,設備物理內存及I/O空間到NT虛擬空間的映射),則可以減少重復開發的工作量,正確性和可靠性更容易得到保障。在此基礎上,利用設備的各種自有特征,自動生成驅動程序成為可能,使驅動程序的開發更為簡化,開發周期更短。集成化的開發環境是高效編程的保證之一,恰恰是DDK所欠缺的,在研究中將力圖解決這個問題。