WDM驅動程式設計

來源:互聯網
上載者:User
WDM驅動程式設計 作者:湯琳 發布時間:2001/03/14
 
文章摘要:
  現在Windows98和Windows2000已經成了主流作業系統的主流,原先用來實現驅動程式的VxD技術隨著Win95的淡出也慢慢地將退出曆史舞台,在Windows98和Windows2000中裝置驅動程式將根據Windows驅動程式模型(WDM)來設計。WDM通過提供一種靈活的方式來簡化驅動程式的開發,在實現對新硬體支援的基礎上減少並降低所必須開發的驅動程式的數量和複雜性。

       

本文:  



WDM驅動程式設計  


一.WDM簡介
  微軟不斷推出新的作業系統,現在Windows98和Windows2000已經成了主流,原先用來實現驅動程式的VxD技術隨著Win95的淡出也慢慢地將退出曆史舞台,在Windows98和Windows2000中裝置驅動程式將根據Windows驅動程式模型(WDM)來設計。WDM通過提供一種靈活的方式來簡化驅動程式的開發,在實現對新硬體支援的基礎上減少並降低所必須開發的驅動程式的數量和複雜性。
  Windows驅動程式模型分兩個方面,除了核心模型描述裝置驅動程式的標準結構外,WDM還為常見類型的裝置實現了一個模組化的、分層次類型的匯流排驅動程式和類驅動程式。匯流排驅動程式實現了支援通用序列匯流排(USB)、IEEE1394(FireWire)協議等。類驅動程式是為實現標準Windows功能提供條件。WDM對標準類介面的支援減少了Windows 95和Windows NT所需的裝置驅動程式的數量和複雜性。在Windows平台上,WDM將成為21世紀主流的驅動模式。
  WDM支援USB、IEEE 1394、ACPI等全新的硬體標準。而且以往在兩個平台上同時運行時需要編寫兩個截然不同的驅動程式,現在只需要編寫一個WDM驅動程式就可以了。WDM驅動程式也是分層的,即不同層上的驅動程式有著不同的優先順序,而Windows 9x下的VxD則沒有此結構。

 

  WDM還引入了功能裝置對象FDO(Functional Device Object)與物理裝置對象PDO(Physical Device Object)兩個新類來描述硬體,一個PDO對應一個真實硬體。一個硬體只允許有一個PDO,卻可以擁有多個FDO,在驅動程式中直接操作的不是硬體而是相應的PDO與FDO。在使用者態和核心態通訊方面,系統為每一個使用者請求打包形成一個IRP結構,將其發送至驅動程式,並通過識別IRP中的PDO來區別是發送給哪一個裝置的。另外,在驅動程式的載入方面,WDM不通過驅動程式名稱識別,而是通過一個128位的通用唯一識別碼GUID來實現驅動程式的識別。我們用來說明裝置驅動程式的分層及調用。
  寫WDM和其它模式驅動程式基本上是相同的,代碼中的主要區別在於如何建立裝置。
  在WDM驅動程式中,隨插即用(PnP)管理器告知何時向系統添加一個裝置,或者從系統刪除裝置。PnP管理器使用安裝的INF檔案尋找新裝置的正確驅動程式;而其它模式驅動程式必鬚髮現它自己的裝置,使用專門的安裝程式安裝。
另外在細節上也存在很多區別,其它模式驅動程式參數一般由註冊表提供,在DriverEntry裡調用讀註冊表的函數,然後根據註冊表再調用CreateDevice,但是WDM一般不是這樣,這是由於Windows 2000下支援PnP,在載入的時候PnP管理器調用AddDevice進入點建立裝置。一般在DriverEntry裡建立的是一個與裝置或者對象毫無關係的虛擬設備,用於管理與Win32的通訊。如果不想對該裝置做什麼特別的處理,或者裝置不複雜,AddDevice可以簡單返回Nt_Success,不用調用CreateDevice。
  另外整個裝置驅動樹也發生了改變,從而使安裝程式發生了很大的改變。WDM本身的PNP管理器被抽象地提升到了ROOT的地位。PNP管理器負責所有的匯流排驅動程式的載入。匯流排驅動程式則負責遍曆所有位於匯流排上的裝置,並且為每個裝置建立相應的裝置對象。當PNP管理器發現一個裝置對象,就尋找該對象對應的Driver。並調用該Driver的ADD DEVICE常式。如果Driver不在記憶體中,就先載入,然後調用ADD DEVICE常式。
  當然,匯流排本身並沒有發出任何訊號告訴PNP管理器自己的存在,所以,匯流排Driver是在NT的安裝時設定的。而ISA裝置並沒有規範,因為需要KMD自己檢查硬體存在及狀態,所以它是老式KMD存在的惟一理由。這也是微軟極力在新規範裡取消ISA匯流排的理由之一。WDM支援PNP協議和PM協議,而且實現時僅僅需要在MAJOR FUNCTION裡加入一些對PNP和PM事件響應的常式即可。
  一個完整的驅動程式要完成以下工作:初始化;建立與刪除裝置;處理應用程式層程式的開啟和關閉控制代碼的請求;處理應用程式層程式的輸入/輸出請求;序列化對裝置的訪問;訪問硬體;調用其他驅動程式;取消I/O請求;逾時I/O請求;處理可熱插拔裝置的加入和刪除事件;電源管理和WMI。

二.開發裝置驅動程式

2.1設計工具DDK的安裝

  編寫WDM裝置驅動程式我們需要Microsoft的驅動程式開發套件DDK。儘管微軟宣稱WDM驅動程式是Windows98和2000之間二進位相容的,為了安全起見我們還是在不同的系統下僅安裝相應的DDK。

(一).Windows 98 DDK的安裝
  這一部分描述如何安裝Windows 98 DDK。我們約定%98DDK%為安裝Windows 98 DDK的根目錄;%MSTOOLS%為微軟SDK平台的根目錄;%VCPPDEV%為安裝的VC++開發環境的根目錄。
  使用DDK的軟體平台通常為Windows 98作業系統和VC++ 4.2或5.0版本,若要編譯視頻捕獲樣本則需要VC++ 5.0版本。你必須在安裝Windows 98 DDK之前先安裝VC++編譯/開發環境,否則運行時,Windows 98 DDK的Setenv.bat檔案將不能建立正確的編譯環境 。閱讀DDK 文檔需要IE 4.01以上版本,如果是從光碟片或需要測試光碟片驅動程式則需要光碟機,16MB記憶體是不可少的,完整安裝需要82MB硬碟空間(最小安裝需要32MB硬碟空間)。
  Windows 98 DDK所帶的所有驅動程式例子都不需要在安裝有SDK的平台下構造。不過,如果你開始開發自己的驅動程式,可能需要Windows 98 DDK中沒有而是在SDK平台中的標頭檔,因此可以考慮兩種方法:拷貝所需的標頭檔或SDK平台的檔案到在%98DDK%和%VCPPDEV%下適當的Include 目錄中;也可以直接安裝SDK平台,編輯%98DDK%/BIN中Setenv.bat檔案,並運行安裝在%MSTOOLS%裡的Setenv.bat檔案。
  用Setup程式安裝DDK,步驟為:
  (1)運行Windows 98 DDK中的SETUP.EXE檔案,按照對話方塊提示安裝Windows 98 DDK到%98DDK%。
  (2)安裝VC++ 5.0到%VCPPDEV%。
  (3)修改CONFIG.SYS增大環境變數空間。在CONFIG.SYS檔案最後加入一行:
  SHELL=C:/WINDOWS/COMMAND.COM /p /e:4096
  在安裝Windows 98 DDK之前,必須先安裝VC++編譯器/開發環境,否則運行時,Win
dows 98 DDK的Setenv.bat批次檔將不能建立正確的環境。
  下面介紹建立Windows 98驅動程式構造環境以及利用構造環境和工具構造驅動程式的方法。
  1. 用SETENV.BAT來安裝驅動程式構造環境
  開始菜單中有"Development Kits/Windows 98 DDK"的目錄。這個目錄包括自由構造環境項和檢查構造環境項。每次重啟作業系統,在構造驅動程式前,單擊這些程式檔案夾中合適的一項。這些項調用%98DDK%/BIN裡的Setenv.bat批次檔來建立正確的環境變數的驅動程式構造環境。

  2. 手工運行SETENV.bat
  在MS-DOS提示符下,或在"開始/運行"中使用下列語句:
  setenv  %98DDK%  [free | checked]
  例如,在C:/98ddk/bin〉提示符下,鍵入setenv C:/98ddk free,其中第一個參數指定DDK被安裝的檔案夾,注意預設安裝是/98ddk;可選的第二個參數說明目標構造環境,預設類型是free。

  3. 構造WDM驅動程式
  使用一系列規則以指定驅動程式怎樣被建立,構造公用程式可用來在Windows 98 和Windows NT平台上構造WDM驅動程式。
  在Windows 98 DDK被安裝之後,WDM驅動程式構造樹的工作例子和組成部分檔案在硬碟上就可以得到了。驅動程式構造樹根目錄在%98DDK%/src。查看%98DDK%/inc裡Makefile.def檔案的內容,以及貫穿驅動程式構造樹的各種的Dirs檔案和源檔案的內容,可以利用這些代碼作為工作執行個體。

  4.構造驅動程式
  在目前的目錄的驅動程式構造樹中建立一個子目錄,然後,運行構造公用程式。在構造樹的目前的目錄中,構造公用程式可以自動建立出驅動程式的原始碼。構造公用程式在Windows 98 DDK例子驅動程式構造樹的根目錄下(%98DDK%/src)運行。例如,如果僅僅對為聲音裝置類構造的例子驅動程式有興趣,可以設定目前的目錄到%98DDK%/src/audio上,然後,運行構造公用程式。

  5.檢查Windows 98 DDK的安裝
  經常使用的構造指令形式為build -cZ ;從而使構造公用程式做相關檔案的掃描,執行完整的建立,並建置錯誤記錄。檢查安裝的方法為:在/〈destination〉/src目錄運行build -cZ,構造安裝的例子驅動程式原始碼的完整集。這個公用程式在構造驅動程式之前構造全部相關檔案,自動建立檔案關聯關係。這個過程可能需要30多分鐘。如果構造沒有完成或報告過多的編譯錯誤,則需要確認是否正確執行了以上的安裝步驟。通過安裝DDK和相應的開發軟體,我們構造好了WDM驅動程式的開發環境。接著,我們就要深入進行設計與開發工作了。
  安裝DDK後,在DDK程式組下有檢查Check和自由Free兩個編譯環境,Check環境用於編譯帶調試資訊的驅動程式,Free則是編譯正式發布版本的環境。通常情況下裝置驅動程式的編譯採用命令列的方式。通過一定的設定可以在VC ++的Integration Environment下編譯。
  一般來說,成功編譯一個最基本的裝置驅動程式需要四個檔案,第一個是驅動程式,即C語言來源程式檔案(例如isousb.c,注意下面所有的例子都是以isousb來說明);第二個是RC檔案(例如isousb.rc);第三個是SOURCES檔案;第四個檔案是MAKEFILE檔案。SOURCES檔案和make檔案類似,用來指定需要編譯的檔案以及需要串連的庫檔案。這三個輔助檔案都很簡單,在DDK samples的每個常式裡都有三個這樣的檔案,依樣畫瓢就能理解它們的結構和意義。

1.舉例分析
  以下以isousb程式為例,設isousb.rc代碼為:
  #include <windows.h>
  #include <ntverp.h>

  #define VER_FILETYPE VFT_DLL
  #define VER_FILESUBTYPE VFT2_UNKNOWN
  #define VER_FILEDESCRIPTION_STR "I82930 Isochronous IO Test Driver"
  #define VER_INTERNALNAME_STR "IsoUsb.sys"
  #define VER_ORIGINALFILENAME_STR "IsoUsb.sys"

  #include "common.ver"
  裝置驅動程式一般都使用Build公用程式來進行,Build只是NMAKE外面的一個外封裝程式。Build本身其實相當簡單,編譯的大部分工作實際上由Build傳遞給NMAKE來進行。

  /SOURCES/
  TARGETNAME=IsoUsb
  TARGETTYPE=DRIVER
  TARGETPATH=$(BASEDIR)/LIB
  DRIVERTYPE=WDM

  INCLUDES=$(BASEDIR)/inc; /
  $(BASEDIR)/src/usb/inc; /
  $(BASEDIR)/src/wdm/usb/inc; /
  .. /../inc

  TARGETLIBS=$(BASEDIR)/lib/*/free/usbd.lib

  USE_MAPSYM=1

  SOURCES= /
  IsoUsb.rc /
  IusbDbg.c /
  IsoUsb.c /
  IsoPnP.c /
  IsoPwr.c /
  IoctlIso.c /
  IsoStrm.c /
  OcrwIso.c
  /end of SOURCES/
  注意SOURCES的檔案名稱沒有任何副檔名。
  # makefile
  ###########################################################################
  #
  # Copyright (C) Microsoft Corporation 1995
  # All Rights Reserved.
  #
  # MAKEFILE for WDM device driver kit
  #
  ###########################################################################

  #
  # DO NOT EDIT THIS FILE!!! Edit ./sources. if you want to add a new source
  # file to this component. This file merely indirects to the real make file
  # that is shared by all the driver components of the Windows NT DDK
  #

  !INCLUDE $(NTMAKEENV)/makefile.def
  # end of makefile
  對所有驅動程式而言,makefile都是一樣的,Microsoft也警告不要編輯這個檔案,如果需要,可以編輯修改sources檔案達到同樣的效果。對於裝置驅動程式,所使用的C編譯器基本上無一例外地選用VC++。

2.編譯的基本步驟
  (1)首先進入check或free編譯環境,初始化DDK編譯環境。
  (2)運行VC安裝目錄下bin目錄下的vcvars32.bat,初始化VC++編譯環境。
  (3)運行Build.exe進行編譯。

(二).Windows2000 DDK的安裝

  由於前面我們已經詳細介紹了Windows98 DDK的安裝,我們在這裡主要介紹一下Windows2000 DDK安裝與Windows98 DDK的不同。
  兩者對系統的要求不同,Windows2000 DDK需要Windows2000或Windows98作業系統,VC++5.0或6.0專業或企業版,至少64MB記憶體,推薦128MB或更多的記憶體,完整安裝需要200MB,而且如果你在Windows2000下安裝的話,必須以管理員的身份登入。

2.2裝置驅動程式的設計
  I/O請求包(IRP)是驅動程式操作的中心,IRP是一個核心對象,它是一個預先定義的資料結構,帶有一組對它進行操作的I/O管理器常式。I/O管理器接收一個I/O請求後分配並初始化一個IRP。一個IRP有一個固定的首部和可變數目的IRP棧單元塊,每個I/O請求有一個主功能代碼(IRP_MJ_XXX)並可能有次功能代碼(IRP_MN_XXX)。設計一個裝置驅動程式,應該支援和其他相同類型裝置的驅動程式相同的IRP_MJ_XXX和IOCTL請求代碼。如果設計一個中介層驅動程式,應該首先確認下層驅動程式所管理的裝置,因為一個高層的驅動程式必須具有低層驅動程式絕大多數IRP_MJ_XXX常式入口。高層驅動程式在接到I/O請求時,在確定自身IRP當前堆棧單元參數有效前提下 ,設定好IRP中下一個低層驅動程式的堆棧單元,然後再調用IoCallDriver將請求傳遞給下層驅動程式處理。一旦決定好了驅動程式應該處理哪些IRP_MJ_XXX,就可以開始確定驅動程式應該有多少個Dispatch常式。當然也可以考慮把某些IRP_MJ_XXX處理的常式合并為同一常式處理。
  一個驅動程式必須為它所管理的每個可能成為I/O請求的目標的物理和邏輯裝置建立 一個Device對象。一些低層的驅動程式還可能要建立一些不確定數目的Device對象。例如一個硬碟驅動程式必須為每一個物理硬碟建立一個Device對象,同時還必須為每個物理磁碟上的每個邏輯分區建立一個Device對象。
  一個高層驅動程式必須為它所代表的虛擬設備建立一個Device對象,這樣更高層的驅動程式才能串連它們的Device對象到這個驅動程式的Device對象。另外,一個高層驅動程式通常為它低層驅動程式所建立的Device對象建立一系列的虛擬或邏輯Device對象。
  儘管可以分階段來設計驅動程式,從而使一個處在開發階段的驅動程式不必一開始就建立出所有它將要處理的所有Device對象,但從一開始就確定好最終要建立的所有Device對象將有助於設計者所要解決的任何同步問題。另外,確定所要建立的Device對象還有助於定義Device對象的Device Extension的內容和資料結構。
  驅動程式的開發是一個從粗到細逐步求精的過程。DDK的src/目錄下有一個龐大的模板代碼,幾乎覆蓋了所有類型的裝置驅動程式、高層驅動程式和過濾器驅動程式。在開始開發驅動程式之前,可以先在這個樣板庫下面尋找是否有和所要開發的類似類型的常式。
  下面筆者將進一步介紹開發驅動程式的基本步驟:

  l.編寫驅動程式架構
  (1)首先編寫一個DriverEntry常式,並在該常式裡調用IoCreateDevice來建立一
個Device對象。在這個常式中必須設定一系列的回調(callback)常式來處理IRP。
  (2)寫一個處理IRP_MJ_CREATE請求的常式的基本架構。如果驅動程式建立了多於一個的Device對象,則必須為IRP_MJ_CLOSE請求寫一個常式。
  (3) 編譯串連驅動程式。

  2.測試驅動程式
  (1)首先在系統中安裝好驅動程式。
  (2)為邏輯裝置名稱和目標Device對象名稱之間建立起符號連結,在前面已經知道Device對象名稱對Win32使用者模式是不可見的,是不能直接通過API來訪問的,Win32 API只能訪問符號連結名。可以通過修改註冊表來建立這兩種名稱之間的符號連結。運行Regedt32.exe在/HKEY_LOCAL_MACHINE/ System/ CurrentControlSet/ Control/ Session Manager/ DOS Devices下建立起符號連結,建立這種符號連結也可以在驅動程式裡調用函數IoCreateSymbolicLink,使用參數傳遞合適的符號連結名和核心裝置名稱。
  (3)完成以上所有的設定並檢查無誤後,我們必須重新啟動Windows系統。
  (4)編寫一個簡單的測試程式調用Win32 API中的CreateFile函數,並以符號連結名開啟這個裝置。如果開啟成功,則成功地寫出了一個最簡單的驅動程式了。支援更多的裝置I/O請求,例如驅動程式可能需要對IRP_MJ_READ請求做出響應(完成後可用ReadFile 函數進行測試)。如果驅動程式需要能夠手工卸載,那麼還必須對IRP_MJ_CLOSE做出響應。為所需要處理的IRP_MJ_XXX寫好處理常式,並在DriverEntry裡面初始化好這些常式入口。一個低層的驅動程式需要一個StartIo、ISR和DpcForIsr常式,可能還需要一個SynchCritSection常式,如果裝置使用了DMA,那麼可能還需要一個AdapterControl常式。
  對於高層驅動程式可能需要一個或多個IoCompletion常式,最起碼完成檢查I/O狀態
塊然後調用IoCompleteRequest的工作。如果需要,還要對Device Extension資料結構和內容做些修改。有一點必須很清楚的,就是代碼運行層級的問題,即IRQL,最常見的層級是PASSIVE_LEVEL、APC_LEVEL、DISPATCH_LEVEL和DIRQL。
  在查閱DDK HELP中的函數說明的時候,要注意函數的可運行層級,比如有的函數只能在PASSIVE_LEVEL下運行,有的函數則可以在DISPATCH_LEVEL以下層級運行,層級越高的時候,對代碼的要求就越嚴格,比如在DISPATCH_LEVEL的時候,就不能使用分頁記憶體。通常情況下應該儘可能讓代碼在低運行層級如PASSIVE_LEVEL下運行,在進階別下運行過長時間將導致系統效率降低、影響系統響應的即時性。但有時候自己無法控制啟動並執行層級,例如在調用低層Driver時使用IoCallDriver,低層Driver響應完畢後會執行completion常式,該常式啟動並執行層級就是由低層Driver來決定。因此在編寫completion常式時,應盡量將這個函數設計成能在DISPATCH_LEVEL層級運行。
  依照以上開發步驟,我們可以設計出全新的WDM裝置驅動程式。

2.3裝置驅動程式的安裝

(一). WDM驅動程式安裝
  驅動程式根據INF檔案的指令進行安裝,將可執行檔複製到正確的位置,並建立各種登錄機碼。一些驅動程式需要佔用一些硬體資源,主要是I/O地址和中斷號,PnP管理器將予以分配。使用後的INF檔案複製到Windows INF子目錄。
INF檔案含有安裝一個WDM裝置驅動程式需要的所有資訊,包括要複製的檔案、要建立的登錄機碼等。INF檔案是一個文字檔,它由節組成,每個節以方括弧內的節名稱開始,以後每一行都是一個簡單的項,或設定一個值。下面我們以DDK中的一個例子簡單介紹一下INF檔案。
  BULKUSB.INF
  [Version]
  Signature="$CHICAGO$"
  Class=USB
  provider=%MSFT%
  LayoutFile=layout.inf

  [SourceDisksNames]
  1="DDK BULKUSB Sample","",1

  [SourceDisksFiles]
  bulkusb.sys=1

  [Manufacturer]
  %MfgName%=Microsoft

  [Microsoft]
  %USB/VID_045E&PID_930A.DeviceDesc%=BULKUSB.Dev, USB/VID_045E&PID_930A

  [PreCopySection]
  HKR,,NoSetupUI,,1

  [DestinationDirs]
  BULKUSB.Files.Ext = 10,System32/Drivers
  BULKUSB.Files.Inf = 10,INF

  [BULKUSB.Dev]
  CopyFiles=BULKUSB.Files.Ext, BULKUSB.Files.Inf
  AddReg=BULKUSB.AddReg

  [BULKUSB.Dev.NT]
  CopyFiles=BULKUSB.Files.Ext, BULKUSB.Files.Inf
  AddReg=BULKUSB.AddReg

  [BULKUSB.Dev.NT.Services]
  Addservice = BULKUSB, 0x00000002, BULKUSB.AddService

  [BULKUSB.AddService]
  DisplayName = %BULKUSB.SvcDesc%
  ServiceType = 1 ; SERVICE_KERNEL_DRIVER
  StartType = 2 ; SERVICE_AUTO_START
  ErrorControl = 1 ; SERVICE_ERROR_NORMAL
  ServiceBinary = %10%/System32/Drivers/BULKUSB.sys
  LoadOrderGroup = Base

  [BULKUSB.AddReg]
  HKR,,DevLoader,,*ntkern
  HKR,,NTMPDriver,,BULKUSB.sys
  HKLM,"System/Currentcontrolset/Services/BulkUsb/Parameters","MaximumTransferSize",0x10001,4096
  HKLM,"System/Currentcontrolset/Services/BulkUsb/Parameters","DebugLevel",0x10001,2

  [BULKUSB.Files.Ext]
  BULKUSB.sys

  [BULKUSB.Files.Inf]
  BulkUsb.Inf

  ;---------------------------------------------------------------;

  [Strings]
  MSFT="Microsoft"
  MfgName="Intel"
  USB/VID_045E&PID_930A.DeviceDesc="BulkUsb.Sys Intel 82930 USB Bulk IO Test Board"
  BULKUSB.SvcDesc="BulkUsb.Sys i82930 Bulk IO test driver"

  我們介紹一下常用的節:
  [Version]
  Signature項為$Windows NT$,$Windows 95$或$Chicago$;
  Class項為系統定義的一個類名字(例中為USB)或使用者指定的新的類名字;
  Provider項為INF檔案的建立者;
  [SourceDisksNames]
  對於每個發行磁碟片或CD-ROM,指定它的描述和可能的打包檔案和目錄;
  [SourceDisksFiles]
  指定檔案名稱、源磁碟ID和可選的子目錄和檔案大小,如果所有檔案都在根目錄下這個節可以為空白;
  [Manufacturer]
  指定廠商名;
  [DestinationDirs]
  對預設檔案複製和指定檔案複製指定目錄;
  [BULKUSB.Dev]
  指定要複製檔案的列表節(BULKUSB.Files.Ext, BULKUSB.Files.Inf)的名稱;指定addreg節(BULKUSB.AddReg)的名稱;
  [BULKUSB.AddService]
  指定驅動程式服務的詳細資料;
  [BULKUSB.AddReg]
  在註冊表中添加新的索引值;
  [Strings]
  指定一些字串;

(二).NT式驅動程式安裝
1.添加註冊表中的索引值
  Windows在引導的時候,通過掃描註冊表構造驅動程式列表。這個列表既包括自啟動的驅動程式,也包括需要手工啟動的驅動程式。這個列表其實就是控制台中裝置 Applet所列出來的所有裝置。所有的裝置驅動程式應該在註冊表的HKEY_LOCAL_MACHINE /System/CurrentControl-Set/Services/下有相應的索引值。這裡的名稱應該和你的驅動程式名稱一致。下面一般有以下索引值:



  Type值為1表示核心模式驅動程式;為2表示檔案系統驅動程式。
  ErrorControl值為0表示日誌記錄錯誤並忽略;值為1表示日誌記錄錯誤並顯示一個
對話方塊;值為2表示日誌記錄錯誤,並用最後的正確配置重新啟動;值為3表示日誌記錄
錯誤,如果已經使用過正確配置,返回失敗。
  在任何一個裝置驅動程式中,上表中的前三項參數都是必需的。

2.控制驅動程式的裝入次序
  有時候控制多個驅動程式的裝入次序是必要的。有時一套驅動程式中的部分程式必須在其他程式啟動的前提下啟動。

3.驅動程式的Start值
  上面註冊表中驅動程式的Start值控制驅動程式在系統啟動的時間。目前,Start可以取以下值,此外為該值留有擴充餘地,以適用於新的要求:
  (l)0x0 (SERVICE_BOOT_START):這個值指定本驅動程式應該由作業系統裝入程式啟
動。一般的驅動程式不會採用本值,因為系統在這個時候幾乎還沒有啟動,大部分系統尚不可用。
  (2)0x1 (SERVICE_SYSTEM_START):該值表示在作業系統裝入後但同時初始化它自己時啟動驅動程式。
  (3)0x2 (SERVICE_AUTO_START):該值表示在整個系統啟動並運行後由服務控制管理員裝入。
  (4)0x3 (SERVICE_DEMAND_START):該值表示該驅動程式必須手工啟動。可以通過控制台的裝置applet或者使用WIN32 API編程來啟動。
  (5)0x4 (SERVICE_DISABLED):表示本驅動程式被禁用。
  注意在調試驅動程式的時候,最好將Start值設定為3來手工啟動,這是因為如果設定為自動啟動,而驅動程式在啟動的過程中又發生了異常錯誤的話,可能導致系統不能啟動。
  如果沒有緊急恢複盤,首先可以嘗試在啟動的時候選擇用已知的配置來啟動系統,看是否能啟動成功。如果失敗,可以用DOS啟動後到/%SystemRoot%/System32/Drivers目錄下將出現問題的驅動程式刪除,然後系統就可以啟動了。
  通過設定Start可以控制驅動程式在不同的時候啟動。但如果要解決依賴性問題,則需要使用Group和DependOnGroup值。
  首先要確定自己的驅動程式使用的Group名,系統有一些定義好的組名,對於當前系統存在的組名,可以觀察註冊表的/HKEY_LOCAL_MACHINE/System/CurrentControl- Set/Control/ServiceGroupOrder/List的索引值。例如該值可以設定為:
  …
  SCSI miniport
  port
  Primary disk
  SCSI class
  SCSI CDROM class
  filter
  boot file system
  …
  這裡每一行都是一個Group名,一般來說某個驅動程式都屬於某一個Group。系統啟動時按照該List下組的順序依次啟動各組裡的驅動程式。DependOnGroup值控制本驅動程式啟動的時候必須先啟動另一組的驅動程式。

4.修改註冊表的方法
  在註冊表裡這些值可以手工修改,也可以自己編程利用WIN32 API進行添加,同時也
可以用ini檔案的方式來添加。然後以ini檔案名稱為參數運行REGINI.EXE。就會自動在註冊表裡添加相應的項。在註冊表裡添加好這些項後,必須重新啟動系統,這樣所添加的裝置驅動程式才能在控制台的裝置applet中列出來,再進行其他動作。

5.啟動裝置驅動程式
  在添加修改好註冊表後,重新啟動系統,如果選擇的Start值是0、1、2,如果一切正常,驅動程式就應該已經啟動起來了。可以觀察控制台的裝置applet中的裝置列表。如果Start選擇的是3,則可以直接啟動。

6.調試
  由於驅動程式的運行層級較高,我們不能將一個沒有經過嚴格測試的程式交給使用者使用。驅動程式的測試可以通過在程式中定義一些輸出的宏來完成,也可以通過一些工具進行原始碼級的調試。有一些跟蹤工具可以協助我們,如Compuware Numega的Driver Monitor和Open System Resources的OSRTracer。DDK還提供了WinDbg偵錯工具,不過要使用這個程式需要兩台通過串列電纜連線或網路連接的PC機,分別運行檢查構造和自由構造。上面提到的Numega還提供SoftICE偵錯工具,相信有不少人用它來破譯軟體密碼吧。
  至此我們已經粗略的介紹了WDM程式的設計方法,在實際的編寫過程中我們可以藉助於DDK的文檔和樣本來協助我們編寫屬於我們自己的驅動程式。

作者會員名:tliwant

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.