天天看點

43、Windows驅動程式模型筆記(一)

1、通常,驅動程式在某些不可預測線程的上下文中應該使用異步方式處理I/O請求。我們使用術語任意線程上下文(arbitrary thread context)來描述驅動程式并不知道(或并不關心)處理器目前執行在哪一個線程上的上下文。<?xml:namespace prefix = o />

2、 Windows 2000使用對稱多處理器模型,即所有的處理器都是相同的,系統任務和使用者模式程式可以執行在任何一個處理器上,并且所有處理器都平等地通路記憶體。多處理器的存在給裝置驅動程式帶來了一個困難的同步問題,因為執行在多個CPU上的代碼可能同時通路共享資料或共享硬體資源。Windows 2000提供了一個同步對象,自旋鎖(spin lock),驅動程式可以使用它來解決多處理器的同步問題。

3、當CPU運作在 PASSIVE_LEVEL級時,目前運作的線程可以被任何優先級大于它的線程搶先。然而,一旦CPU的IRQL大于PASSIVE_LEVEL級,線程搶先将不再發生,此時CPU執行在使CPU越過PASSIVE_LEVEL級的任意線程上下文中。但是,運作在任何IRQL級上的活動都可以被更高 IRQL級上的活動中斷。是以驅動程式必須假定在任何時刻都可能失去控制權,而此時系統可能需要執行更基本的任務。

4、為了實作可配置性,首先應該在代碼中避免直接引用硬體,即使是在平台相關的條件編譯塊中也是這樣。應該使用HAL工具或調用低級總線驅動程式,或者實作一個标準的或定制的控制接口,并通過控制台程式與使用者互動。另外,還應該支援Windows管理儀器(WMI)控件,這種控件允許使用者和管理者在分布式企業環境中配置硬體特征。最後,應該使用系統資料庫作為配置資訊的資料庫,這可以使配置資訊在系統重新啟動後仍然存在。

5、為了實作這種可移植性,驅動程式應該全部用C寫,并且隻使用ANSI C标準規定的語言元素。應避免使用編譯器廠商專有的語言特征,并避免使用沒有被作業系統核心輸出的運作時間庫函數(參見第三章)。如果不能避免驅動程式中的平台依賴,至少應該用條件編譯指令隔離這些代碼。

6、可以把一個完整的驅動程式看作是一個容器,它包含許多例程,當作業系統遇到一個IRP時,它就調用這個容器中的例程來執行該IRP的各種操作。

可以把一個完整的驅動程式看作是一個容器,它包含許多例程,當作業系統遇到一個IRP時,它就調用這個容器中的例程來執行該IRP的各種操作。有些例程,例如DriverEntry和AddDevice,還有與幾種IRP對應的派遣函數将出現在每一個這樣的容器中。需要對IRP排隊的驅動程式一般都有一個 StartIo例程。執行DMA傳輸的驅動程式應有一個AdapterControl例程。大部分能生成硬體中斷的裝置,其驅動程式都有一個中斷服務例程 (ISR)和一個推遲過程調用(DPC)例程。驅動程式一般都有幾個支援不同類型IRP的派遣函數,其中三個派遣函數是必須的。是以,WDM驅動程式開發 者的一個任務就是為這個容器選擇所需要的例程。

43、Windows驅動程式模型筆記(一)

圖示 P21 1-5 WDM驅動程式“容器”中的内容

7、有三種系統資料庫鍵負責配置。它們是硬體(hardware)鍵、類 (class)鍵、服務(service)鍵。必須明确一點,這些名字(指hardware、class、service)并不是某個專用子鍵的名稱:它 們是這三種鍵的一般稱謂,其具體的路徑名要取決于它們所屬的裝置。概括地講,硬體鍵包含單個裝置的資訊,類鍵涉及所有相同類型裝置的共同資訊,服務鍵包含 驅動程式資訊。有時人們用“執行個體(instance)鍵”和“軟體(software)鍵”來代表硬體鍵和服務鍵。

    裝置的硬體鍵出現在系統資料庫local machine分支的\System\CurrentControlSet\Enum子鍵上。

    應用程式經常需要通路系統資料庫中關于硬體裝置的資訊。為了使這成為可能而同時又不暴露重要的Enum鍵,Microsoft提供了一組SetupDiXxx函數。

   裝置接口的符号連接配接名(通過枚舉該接口GUID的所有執行個體或者從WM_DEVICECHANGE消息的參數中獲得這個名字)。ClassGUID是裝置類GUID(全局唯一辨別符)的ASCII形式;在效果上,它是一個指向該裝置類鍵的指針。Service指向服務鍵。

類鍵 所有裝置類的類鍵都出現在HKLM\System\CurrentControlSet\Control\Class鍵中。它們的鍵名是由Microsoft賦予的GUID值。

服務(或軟體)鍵 對裝置驅動程式重要的最後一個鍵是服務鍵。它指出驅動程式執行檔案的位置,以及控制驅動程式裝入的一些參數。服務鍵位于HKLM\System\CurrentControlSet\Services鍵中。

    當我說系統“裝入”一個驅動程式時,是指系統把驅動程式的映像映射到虛拟記憶體中,并重定位記憶體參考,最後調用驅動程式的主入口點。主入口點通常命名為 DriverEntry。我将在本章後面講述DriverEntry函數。如果驅動程式已經在記憶體中,則裝入過程僅僅是增加驅動程式映像的參考計數。

8、驅動程式的裝入順序并不是很重要。系統以PnP管理器裝入驅動程式的順序調用驅動程式的AddDevice函數,而這個順序與裝置對象在裝置堆棧中出現的順序完全一緻。

43、Windows驅動程式模型筆記(一)

圖示2-2 裝置遞歸枚舉過程

圖示2-2顯示了一個由多個裝置堆棧組成的樹形結構,但這并不表示IRP必須從上一層的PDO流向下一層的FiDO。實際上,一個堆棧的PDO驅動程式就是其下一層堆棧的FDO驅動程式,見圖示2-2中的陰影塊。當驅動程式以PDO角色接收到一個IRP時,它對該IRP執行一些操作但不發出這個或其它IRP到裝置(以FDO角色)。相反,當總線驅動程式以FDO角色接收到一個IRP時,它可能需要向裝置發送某些IRP(以PDO角色)。

43、Windows驅動程式模型筆記(一)

圖示 圖2-8 裝置(位于二級總線)讀請求處理流程