Windows 2000內(nèi)核模式驅(qū)動(dòng)程序設(shè)計(jì)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
摘要:介紹了Windows2000驅(qū)動(dòng)程序模型的基本結(jié)構(gòu)、設(shè)計(jì)和開(kāi)發(fā)的基本問(wèn)題。并以PCI接口的ATM信令接口卡開(kāi)發(fā)的驅(qū)動(dòng)程序部分為例,簡(jiǎn)單介紹了驅(qū)動(dòng)程序開(kāi)發(fā)的方法和步驟.并介紹了驅(qū)動(dòng)程序開(kāi)發(fā)環(huán)境的設(shè)置及編譯方法。這種內(nèi)核模式驅(qū)動(dòng)程序設(shè)計(jì)的開(kāi)發(fā)過(guò)程得到了簡(jiǎn)化,并降低了其復(fù)雜性。
關(guān)鍵詞:Windows2000;驅(qū)動(dòng)程序模型;ATM信令接口
0引言
設(shè)備驅(qū)動(dòng)程序是直接同硬件打交道的軟件模塊。在Windows2000中,微軟公司在WindowsNT4.0的驅(qū)動(dòng)程序結(jié)構(gòu)基礎(chǔ)上,同時(shí)引入了Windows9X的即插即入特性,推出了新的驅(qū)動(dòng)程序結(jié)構(gòu)模式(WDM)。WDM通過(guò)提供一種靈活的方式來(lái)簡(jiǎn)化驅(qū)動(dòng)程序的開(kāi)發(fā),在實(shí)現(xiàn)對(duì)新硬件支持的基礎(chǔ)上減少并降低所必須開(kāi)發(fā)的驅(qū)動(dòng)程序的數(shù)量和復(fù)雜性。在Windows2000中的驅(qū)動(dòng)程序可以分為2大類:用戶模式驅(qū)動(dòng)程序和內(nèi)核模式的驅(qū)動(dòng)程序。用戶模式驅(qū)動(dòng)程序是與子系統(tǒng)特定相關(guān)的,它包含了Win32多媒體驅(qū)動(dòng)程序、支持MS-DOS應(yīng)用程序的虛擬設(shè)備驅(qū)動(dòng)程序VDD(VirtualDeviceDriver)。內(nèi)核模式驅(qū)動(dòng)程序有3種基本類型,每一種都有稍微不同的結(jié)構(gòu)和完全不同的功能,即最高層驅(qū)動(dòng)程序(如文件系統(tǒng)驅(qū)動(dòng)程序(FSD))、中間層驅(qū)動(dòng)程序(例如虛擬磁盤(pán)、鏡像或設(shè)備類型特定的外圍設(shè)備)、底層驅(qū)動(dòng)程序(例如PnP硬件總線驅(qū)動(dòng)程序)。在Windows2000操作系統(tǒng)下的驅(qū)動(dòng)程序開(kāi)發(fā)分為3個(gè)主要的領(lǐng)域:WDM驅(qū)動(dòng)程序、文件系統(tǒng)驅(qū)動(dòng)程序和小端口驅(qū)動(dòng)程序,見(jiàn)圖1。其中小端口驅(qū)動(dòng)程序針對(duì)的是顯示設(shè)備、SCSI和網(wǎng)絡(luò)設(shè)備等特定領(lǐng)域;文件系統(tǒng)驅(qū)動(dòng)程序針對(duì)的是存儲(chǔ)設(shè)備;WDM驅(qū)動(dòng)程序針對(duì)的則是計(jì)算機(jī)應(yīng)用系統(tǒng)開(kāi)發(fā)所面對(duì)的大多數(shù)情況。本文我們討論了WDM內(nèi)核模式的驅(qū)動(dòng)程序設(shè)計(jì)的一般問(wèn)題,雖然其他類型驅(qū)動(dòng)程序與WDM內(nèi)核模式驅(qū)動(dòng)程序開(kāi)發(fā)有所不同,但只要掌握了WDM內(nèi)核模式驅(qū)動(dòng)程序開(kāi)發(fā)的基礎(chǔ),結(jié)合2種基本類型的本身特點(diǎn),就能夠很快掌握設(shè)計(jì)方法。
1WDM的基本原理
WDM是一個(gè)模塊化的、分層次類型的微型驅(qū)動(dòng)程序結(jié)構(gòu),層次結(jié)構(gòu)如圖2所示,其中左邊是一個(gè)設(shè)備對(duì)象堆棧,右邊為驅(qū)動(dòng)程序的分層結(jié)構(gòu)。在WDM驅(qū)動(dòng)程序模型中,每個(gè)硬件至少要包含功能驅(qū)動(dòng)程序和總線驅(qū)動(dòng)程序2個(gè)層??偩€驅(qū)動(dòng)程序?yàn)榭偩€上發(fā)現(xiàn)的每個(gè)設(shè)備創(chuàng)建物理設(shè)備對(duì)象PDO,每個(gè)功能設(shè)備驅(qū)動(dòng)程序創(chuàng)建自己的功能設(shè)備對(duì)象FDO。在驅(qū)動(dòng)程序中不是直接操作硬件,而是操作相應(yīng)的PDO與FDO。來(lái)自用戶模式API的I/O請(qǐng)求包(IRP)送到設(shè)備堆棧的最上層驅(qū)動(dòng)程序,然后逐漸過(guò)濾到下層的驅(qū)動(dòng)程序。每一層驅(qū)動(dòng)程序都可以決定如何處理IRP。內(nèi)核模式的WDM驅(qū)動(dòng)程序有著可移植性、可配置性、基于對(duì)象、包驅(qū)動(dòng)等共有的屬性。
用戶態(tài)程序和內(nèi)核通過(guò)設(shè)備對(duì)象訪問(wèn)設(shè)備驅(qū)動(dòng)程序的設(shè)備。WDM驅(qū)動(dòng)程序有2種方法提供
Win32程序可用的名稱,舊的方法是在驅(qū)動(dòng)程序的設(shè)備創(chuàng)建時(shí),通過(guò)函數(shù)IoCreate-SymbolicLink創(chuàng)建一個(gè)符號(hào)鏈接名,新的方法是使用128位的設(shè)備接口標(biāo)識(shí)(GUID)。在驅(qū)動(dòng)程序編寫(xiě)中,該GUID可以通過(guò)Windows提供的guidgen.exe工具生成。
2WDM驅(qū)動(dòng)程序的結(jié)構(gòu)及設(shè)計(jì)
內(nèi)核模式的驅(qū)動(dòng)程序不同于常規(guī)的應(yīng)用程序,可以把一個(gè)完整的驅(qū)動(dòng)程序看作是一個(gè)容器,它包含許多例程,當(dāng)操作系統(tǒng)遇到一個(gè)IRP時(shí),它就調(diào)用這個(gè)容器中的例程來(lái)執(zhí)行該IRP的各種操作。圖3表示了這一概念。在每一個(gè)WDM驅(qū)動(dòng)程序中,都必須擁有DriverEntry、AddDevice、DispatchPnP、DispatchPower和DispatchWmi這5個(gè)例程,其他的例程則是可選的。需要對(duì)IRP排隊(duì)的驅(qū)動(dòng)程序一般都有一個(gè)StartIo例程,執(zhí)行DMA傳輸?shù)尿?qū)動(dòng)程序應(yīng)有一個(gè)AdapterControl例程。大部分能生成硬件中斷的設(shè)備,其驅(qū)動(dòng)程序都有一個(gè)中斷服務(wù)例程(ISR)和一個(gè)延遲過(guò)程調(diào)用(DpcForIsr)例程。驅(qū)動(dòng)程序一般都有幾個(gè)支持不同類型IRP的分發(fā)例程。WDM驅(qū)動(dòng)程序開(kāi)發(fā)者的主要任務(wù)就是為如圖3所示的容器選擇,并完成所需要的例程。
當(dāng)I/O管理器裝入驅(qū)動(dòng)程序時(shí),它調(diào)用每個(gè)驅(qū)動(dòng)程序必須有的DriverEntry例程,以用來(lái)初始化驅(qū)動(dòng)程序范圍的數(shù)據(jù)結(jié)構(gòu)和資源。一般來(lái)說(shuō),在DriverEntry例程中通常完成以下功能:①找到所要控制的硬件;②在驅(qū)動(dòng)程序?qū)ο笾性O(shè)置驅(qū)動(dòng)程序的Dispatch-,AddDevice,Startio(如果有)和UN-LOAD(如果有)等分發(fā)例程的程序的入口點(diǎn);③建立所有驅(qū)動(dòng)程序?qū)ο蠡蚱渌到y(tǒng)資源;④返回的NTSTATUS表明驅(qū)動(dòng)程序是否成功裝入,并能接收和處理來(lái)自PnP管理器的配置、增加(AddDevice)及啟動(dòng)其設(shè)備的請(qǐng)求。對(duì)于功能驅(qū)動(dòng)程序,AddDevice函數(shù)的基本職責(zé)是創(chuàng)建一個(gè)設(shè)備對(duì)象并把它聯(lián)接到以PDO為底的設(shè)備堆棧中。分發(fā)(Dispatch)例程是設(shè)備驅(qū)動(dòng)程序提供的主要函數(shù)。當(dāng)被調(diào)用去執(zhí)行一個(gè)I/O操作時(shí),Windows2000通過(guò)實(shí)現(xiàn)Dispatch例程來(lái)處理來(lái)自用戶模式應(yīng)用程序的請(qǐng)求或來(lái)自系統(tǒng)的其他地方的請(qǐng)求。
一個(gè)完整的驅(qū)動(dòng)程序要完成以下工作:初始化;創(chuàng)建與刪除設(shè)備;處理應(yīng)用層程序的打開(kāi)和關(guān)閉句柄的請(qǐng)求;處理應(yīng)用層程序的輸入/輸出請(qǐng)求;串行化對(duì)設(shè)備的訪問(wèn);訪問(wèn)硬件;調(diào)用其他驅(qū)動(dòng)程序;取消I/O請(qǐng)求;處理可熱插拔設(shè)備的加入和刪除事件;電源管理和WMI;對(duì)能夠產(chǎn)生中斷的設(shè)備進(jìn)行中斷處理。
操作系統(tǒng)使用I/O請(qǐng)求包(IRP)的數(shù)據(jù)結(jié)構(gòu)與內(nèi)核模式驅(qū)動(dòng)程序通信。IRP是一個(gè)內(nèi)核對(duì)象,它是一個(gè)預(yù)先定義的數(shù)據(jù)結(jié)構(gòu),帶有一組對(duì)它進(jìn)行操作的I/O管理器例程。I/O管理器接收一個(gè)I/O請(qǐng)求后分配并初始化一個(gè)IRP。一個(gè)IRP有一個(gè)固定的首部和可變數(shù)目的IRP堆棧單元塊,每個(gè)堆棧單元塊都對(duì)應(yīng)一個(gè)將處理該IRP的驅(qū)動(dòng)程序,因此這些堆棧塊至少應(yīng)與驅(qū)動(dòng)程序堆棧中將要處理這一請(qǐng)求的驅(qū)動(dòng)程序數(shù)目一樣多。每個(gè)I/O請(qǐng)求有一個(gè)主功能代碼(IRP_M(jìn)J_XXX),并可能有次功能代碼(IRP_M(jìn)N_XXX)。主功能代碼決定了該I/O請(qǐng)求調(diào)用的分發(fā)例程的驅(qū)動(dòng)程序入口點(diǎn)。分發(fā)例程接收到I/O請(qǐng)求后進(jìn)行如下處理:確認(rèn)I/O請(qǐng)求的合法性;盡可能在分發(fā)例程中直接完成該I/O請(qǐng)求;如果該請(qǐng)求不能在驅(qū)動(dòng)程序的分發(fā)例程中被處理完,驅(qū)動(dòng)程序就把這個(gè)請(qǐng)求排進(jìn)隊(duì)列,以便以后完成處理。WDM驅(qū)動(dòng)程序提供了2種I/O請(qǐng)求排隊(duì)的方法:I/O管理器管理的系統(tǒng)排隊(duì)和驅(qū)動(dòng)程序自己管理的驅(qū)動(dòng)程序排隊(duì)。[!--empirenews.page--]
在Windows2000和Windows98中,通過(guò)使用總線驅(qū)動(dòng)程序,PnP管理器能夠自動(dòng)檢測(cè)硬件和分配I/O資源。在WDM驅(qū)動(dòng)程序中PnP管理器使用主功能代碼為IRP-MJ-PNP的I/O請(qǐng)求包與設(shè)備驅(qū)動(dòng)程序交換信息和請(qǐng)求,完成對(duì)硬件設(shè)備的檢測(cè)和配置工作。PnP請(qǐng)求包完成2種功能:指示驅(qū)動(dòng)程序何時(shí)又如何配置和取消硬件及驅(qū)動(dòng)程序本身的設(shè)置;指導(dǎo)驅(qū)動(dòng)程序完成一系列的狀態(tài)轉(zhuǎn)換。PnP請(qǐng)求可以包含二十多個(gè)次功能代碼,部分功能代碼(如IRP-READ-CONFIG,IRP-MN-QUERY-RE-SOURCE-REQUIREMENTS等)只能由總線驅(qū)動(dòng)程序處理,功能驅(qū)動(dòng)程序和過(guò)濾驅(qū)動(dòng)程序只是將該IRP請(qǐng)求下傳到總線驅(qū)動(dòng)程序。對(duì)功能驅(qū)動(dòng)程序和過(guò)濾驅(qū)動(dòng)程序中比較重要的IRP-MN-START-DEVICE用來(lái)通知功能驅(qū)動(dòng)程序其硬件被賦予了什么的I/O資源,以及指導(dǎo)功能驅(qū)動(dòng)程序做任何必要的硬件或軟件設(shè)置,以便設(shè)備能正常工作。IRP-MN-REMOVE-DEVICE告訴功能驅(qū)動(dòng)程序關(guān)閉設(shè)備并釋放與之關(guān)聯(lián)的設(shè)備對(duì)象。
驅(qū)動(dòng)程序的ISR和DpcForIsr在設(shè)備產(chǎn)生中斷時(shí)共同向設(shè)備提供服務(wù)。當(dāng)設(shè)備產(chǎn)生中斷時(shí),驅(qū)動(dòng)程序的ISR將被調(diào)用,ISR通過(guò)詢問(wèn)設(shè)備硬件收集有關(guān)的硬件設(shè)備信息,并盡可能地處理,如果不可能完全處理該中斷請(qǐng)求,就將中斷信息傳遞給Dpc-ForIsr進(jìn)行處理。ISR是運(yùn)行在DIRQL中斷請(qǐng)求級(jí)的,在運(yùn)行時(shí),會(huì)阻止在同一處理器上的所有設(shè)備發(fā)出的具有更低的DIRQL的中斷,因此在驅(qū)動(dòng)程序的編寫(xiě)時(shí),ISR應(yīng)盡可能快地返回控制。另外,ISR可以與驅(qū)動(dòng)程序的其它部分共享數(shù)據(jù)和硬件資源,因此需要注意同步問(wèn)題的處理。
3WDM驅(qū)動(dòng)程序開(kāi)發(fā)環(huán)境及編譯
Windows2000下編寫(xiě)驅(qū)動(dòng)程序的環(huán)境被稱為DDKForMicrosoftWindows2000或Windows2000DDK,DDK是一個(gè)命令行下的工作環(huán)境。在安裝DDK前需要先安裝Micro-softVisualC++和Win32SDK(可選)。對(duì)驅(qū)動(dòng)程序的編譯可以通過(guò)設(shè)置VC++的項(xiàng)目設(shè)置,在VC++中直接編譯驅(qū)動(dòng)程序,但改變?cè)O(shè)置的工作較繁且易出錯(cuò),因此DDKbuild.exe編譯聯(lián)接器是構(gòu)造驅(qū)動(dòng)程序的主要工具。它從配置文件Sources中讀出待編譯的程序的配置,包括源文件、目標(biāo)文件等,從環(huán)境變量Include中得到引用文件的地址,然后調(diào)用VisualC++的編譯聯(lián)接器Nmake.exe進(jìn)行實(shí)際的編譯聯(lián)接工作。
另外,build編譯聯(lián)接器還可以通過(guò)查看DIRS文件中的偽指令,確定要編譯的驅(qū)動(dòng)程序目錄列表。日志文件build.log、build.wrn,build.err中分別記錄了編譯聯(lián)接中執(zhí)行的命令行、遇到的錯(cuò)誤和警告。編譯完成后的文件后綴為.sys。
驅(qū)動(dòng)程序的調(diào)試是在原代碼級(jí)進(jìn)行的,可以用微軟公司提供的WinDbg調(diào)試工具,但需要在兩臺(tái)以串口聯(lián)接的計(jì)算機(jī)上進(jìn)行。而NUMEGA公司的SOFTICE比較方便地在一臺(tái)計(jì)算機(jī)上進(jìn)行核心代碼的調(diào)試。
4ATM信令接口卡的驅(qū)動(dòng)例程分析
我們開(kāi)發(fā)的ATM信令接口卡硬件符合PCI2.1標(biāo)準(zhǔn),其與應(yīng)用程序的數(shù)據(jù)傳輸為DMA方式。主要部分代碼如下。
在該驅(qū)動(dòng)程序入口部分中我們完成了各個(gè)分發(fā)例程入口的設(shè)置工作。
AtmPnp例程中完成對(duì)硬件資源的的檢測(cè)和配置工作,并且初始化請(qǐng)求隊(duì)列,獲得完成DMA傳輸?shù)腄MA適配器對(duì)象,掛接中斷處理對(duì)象等功能。
在AddDevice函數(shù)調(diào)用IoCreateDevice函數(shù)中創(chuàng)建一個(gè)設(shè)備對(duì)象,并通過(guò)調(diào)用IoAttachDe-viceToDeviceStack把它聯(lián)接到以PDO為底的設(shè)備堆棧中。
在PnP例程中對(duì)IRP-MN-START-DEVICE的處理代碼如下。
在處理中斷資源時(shí)給出的IoConnectInterrupt函數(shù)掛接了中斷處理函數(shù)AtmHandlerInter-rupt。
其他函數(shù)實(shí)現(xiàn)不再一一介紹。在具體實(shí)現(xiàn)的數(shù)據(jù)的傳輸、工作模式的設(shè)置等功能與所使用的硬件的寄存器的工作模式有關(guān)。在設(shè)計(jì)的過(guò)程中,應(yīng)該注意每個(gè)例程的運(yùn)行中斷級(jí)。在處理I/O請(qǐng)求時(shí),應(yīng)根據(jù)硬件的特性和API的要求決定IRP隊(duì)列的方式及取消IRP的例程的編寫(xiě)。
在編寫(xiě)驅(qū)動(dòng)程序前,應(yīng)該盡量了解硬件本身。這包括硬件的總線結(jié)構(gòu)、控制寄存器的訪問(wèn)方式、中斷行為、數(shù)據(jù)傳輸機(jī)制和設(shè)備內(nèi)存等。
5小結(jié)
驅(qū)動(dòng)程序的編寫(xiě)是較復(fù)雜的過(guò)程,因驅(qū)動(dòng)程序是操作系統(tǒng)信任的組件,任何細(xì)小的錯(cuò)誤可能引起操作系統(tǒng)的崩潰,在驅(qū)動(dòng)程序編寫(xiě)過(guò)程中,應(yīng)該反復(fù)測(cè)試所寫(xiě)的代碼,并遵循驅(qū)動(dòng)程序的規(guī)則??傊_(kāi)發(fā)驅(qū)動(dòng)程序的工作與開(kāi)發(fā)Windows應(yīng)用程序開(kāi)發(fā)是完全不同的,且與驅(qū)動(dòng)程序緊密相連的硬件都有自己的硬件和軟件規(guī)范,本文從一般驅(qū)動(dòng)程序概念出發(fā),給出了驅(qū)動(dòng)程序的總體描述和組成部分,并以部分例程代碼為例給出了驅(qū)動(dòng)程序的基本組成結(jié)構(gòu)和注意問(wèn)題。要想能夠很好掌握驅(qū)動(dòng)程序開(kāi)發(fā),最根本是閱讀DDK文檔并實(shí)踐編寫(xiě)驅(qū)動(dòng)程序。[!--empirenews.page--]