windows設(shè)備驅(qū)動(dòng)程序_第1頁(yè)
windows設(shè)備驅(qū)動(dòng)程序_第2頁(yè)
windows設(shè)備驅(qū)動(dòng)程序_第3頁(yè)
windows設(shè)備驅(qū)動(dòng)程序_第4頁(yè)
windows設(shè)備驅(qū)動(dòng)程序_第5頁(yè)
已閱讀5頁(yè),還剩22頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

匯報(bào)人:邢成婧玉軟工(實(shí))11401Windows設(shè)備驅(qū)動(dòng)程序前言Linux是一種日趨成熟完善的操作系統(tǒng).越來越多的軟硬件廠商開始使用Linux平臺(tái)來開發(fā)自己的產(chǎn)品,因而對(duì)基于該平臺(tái)的設(shè)備驅(qū)動(dòng)程序的需求也愈來愈多。同時(shí)PCI總線作為一個(gè)具有兼容性強(qiáng)、平臺(tái)無關(guān)性等特點(diǎn)從的計(jì)算機(jī)總線標(biāo)準(zhǔn)。日前得到了廣泛的應(yīng)用。目錄0304編寫驅(qū)動(dòng)程序的基礎(chǔ)知識(shí)驅(qū)動(dòng)中使用鏈表01驅(qū)動(dòng)開發(fā)環(huán)境的創(chuàng)建02驅(qū)動(dòng)程序結(jié)構(gòu)1驅(qū)動(dòng)開發(fā)環(huán)境的搭建01OPTION關(guān)于DDK02OPTION關(guān)于驅(qū)動(dòng)程序的編譯03OPTION關(guān)于驅(qū)動(dòng)程序的運(yùn)行關(guān)于DDK開發(fā)驅(qū)動(dòng)程序必備的一個(gè)東西就是DDK(DeviceDevelopmentKit,設(shè)備驅(qū)動(dòng)開發(fā)包),它跟我們?cè)趓ing3常聽到的SDK差不多,只不過它們分別支持開發(fā)不同的程序而已。DDK和微軟其他的產(chǎn)品一樣,具有良好的向后兼容性,比如你用DDK2000開發(fā)的驅(qū)動(dòng)在DDKXP里面同樣可以編譯,但反之卻不能保證DriverStudio之類的驅(qū)動(dòng)開發(fā)工具,其實(shí)那只是對(duì)DDK的簡(jiǎn)單封裝,跟SDK與MFC的關(guān)系差不多,不過DriverStudio不僅僅是對(duì)DDK的封裝,而是個(gè)完整的開發(fā)工具包,它提供了很多有用的工具用于驅(qū)動(dòng)程序的開發(fā)和調(diào)試,不過這些工具可以單獨(dú)提取出來使用?!?sys”文件,同時(shí)還需要自己編寫makefile和sources文件。對(duì)于使用VC開始學(xué)習(xí)編程的人們來說,makefile概念有點(diǎn)可能有點(diǎn)陌生。實(shí)際上VC本身只是個(gè)框架,“編譯”這個(gè)工作還是由一個(gè)名為“cl.exe”的命令行工具執(zhí)行的,VC不過是通過一個(gè)良好的界面幫我們完成了一些參數(shù)設(shè)置的工作。使用VC來編譯驅(qū)動(dòng)程序是可行的。VC6.0到新的VS2008都沒有被遺漏。

使用EasySys這個(gè)小工具,可以通過簡(jiǎn)單的設(shè)置生成一個(gè)完整的“.dsw”工程。關(guān)于驅(qū)動(dòng)程序的編譯關(guān)于驅(qū)動(dòng)程序的運(yùn)行通常生成的驅(qū)動(dòng)程序格式都是“.sys”,雖然它也是PE格式,但不能直接運(yùn)行,必須被加載到系統(tǒng)中。因此編寫好一個(gè)驅(qū)動(dòng)程序后,如果想運(yùn)行查看結(jié)果,則必須使用一些工具來進(jìn)行加載。使用一個(gè)名為“KmdManager”的小工具來加載驅(qū)動(dòng)。運(yùn)行界面如圖2驅(qū)動(dòng)程序結(jié)構(gòu)01驅(qū)動(dòng)程序頭文件02驅(qū)動(dòng)程序入口點(diǎn)03創(chuàng)建設(shè)備歷程04卸載驅(qū)動(dòng)歷程

NT式驅(qū)動(dòng)需要導(dǎo)入的頭文件是“ntddk.h”,而WDM式驅(qū)動(dòng)需要導(dǎo)入的“wdm.h”,即:#include“ntddk.h”;。在驅(qū)動(dòng)中用到的變量或函數(shù)都需要指定分配在分頁(yè)或非分頁(yè)內(nèi)存中,分頁(yè)內(nèi)存在物理內(nèi)存不夠的情況下可能會(huì)被交換出去,對(duì)于一些需要高IRQL的例程絕對(duì)不能被交換出頁(yè)面,因此它們必須被定義為非分頁(yè)內(nèi)存。通常來說在驅(qū)動(dòng)程序的自定義頭文件中都是定義了一些宏或函數(shù)聲明。驅(qū)動(dòng)程序頭文件驅(qū)動(dòng)程序入口點(diǎn)在驅(qū)動(dòng)對(duì)象DriverObject中,有個(gè)函數(shù)指針數(shù)組MajorFunction,它里面的每一個(gè)元素都記錄著一個(gè)函數(shù)的地址對(duì)應(yīng)著相應(yīng)的IRP,我們可以通過簡(jiǎn)單地設(shè)置這個(gè)數(shù)組將IRP與相應(yīng)的派遣函數(shù)關(guān)聯(lián)起來。由于在進(jìn)入DriverEntry之前,I/O管理器會(huì)_IopInvalidDeviceRequest的地址填滿整個(gè)MajorFunction數(shù)組,因此除了我們自行設(shè)置過的IRP之外,其他的IRP都與系統(tǒng)默認(rèn)的_IopInvalidDeviceRequest函數(shù)關(guān)聯(lián)。

驅(qū)動(dòng)中的例程實(shí)際上就是函數(shù)的另外一種說法,實(shí)際上例程與函數(shù)還是有所區(qū)別的。創(chuàng)建設(shè)備是在DriverEntry中完成的創(chuàng)建設(shè)備歷程創(chuàng)建設(shè)備歷程//創(chuàng)建設(shè)備對(duì)象

RtlInitUnicodeString(&ntDeviceName,TEST_DEVICE_NAME_W);Status=IoCreateDevice(DriverObject,sizeof(DEVICE_EXTENSION),//DeviceExtensionSize&ntDeviceName,//DeviceNameFILE_DEVICE_TEST,//DeviceType0,//DeviceCharacteristicsTRUE,//Exclusive&deviceObject//[OUT]);

if(!NT_SUCCESS(Status))

{KdPrint(("[Test]IoCreateDeviceErrorCode=0x%X\n",Status));returnStatus;}deviceExtension=(PDEVICE_EXTENSION)deviceObject->DeviceExtension;//創(chuàng)建符號(hào)鏈接RtlInitUnicodeString(&dosDeviceName,TEST_DOS_DEVICE_NAME_W);Status=IoCreateSymbolicLink(&dosDeviceName,&ntDeviceName);if(!NT_SUCCESS(Status)){KdPrint(("[Test]IoCreateSymbolicLinkErrorCode=0x%X\n",Status));IoDeleteDevice(deviceObject);returnStatus;

}卸載驅(qū)動(dòng)例程是我們?cè)贒riverEntry中自己定義的,當(dāng)驅(qū)動(dòng)被卸載時(shí)I/O管理器負(fù)責(zé)調(diào)用該例程,它主要做一些掃尾處理的工作。相關(guān)代碼如下所示:UNICODE_STRINGdosDeviceName;

//釋放其他資源

//刪除符號(hào)鏈接

RtlInitUnicodeString(&dosDeviceName,TEST_DOS_DEVICE_NAME_W);IoDeleteSymbolicLink(&dosDeviceName);//刪除設(shè)備對(duì)象

IoDeleteDevice(DriverObject->DeviceObject);KdPrint(("[Test]Unloaded"));要想輸出一些信息,就需要調(diào)用DbgPrint函數(shù),不過這個(gè)函數(shù)輸出的信息我們無法直接看到,需要使用一些專門的工具,比如DbgView等。有些內(nèi)容我們只想在調(diào)試版輸出,在發(fā)行版忽略,因此DDK中定義了一個(gè)宏KdPrint,它在發(fā)行版不被編譯,只在調(diào)試版才會(huì)運(yùn)行。KdPrint的用法很奇怪,由于它的定義:#defineKdPrint(_x_)DbgPrint_x_,這就導(dǎo)致了它的用法很奇怪,在使用時(shí)外層要有兩個(gè)連續(xù)的括號(hào)。卸載設(shè)備例程編寫驅(qū)動(dòng)程序的基礎(chǔ)知識(shí)ABCD示例程序內(nèi)核模式下的字符串操作內(nèi)核模式下各種開頭函數(shù)的區(qū)別關(guān)系內(nèi)核模式下的字符串操作內(nèi)核模式與用戶模式一樣都是有ANSI和UNICODE兩種字符串,Windows內(nèi)核是使用Unicode編碼的,ANSI只在很少的特殊場(chǎng)合才會(huì)使用,而這種場(chǎng)合往往是非常罕見的,因此不考慮ANSI字符串。Unicode字符串有一個(gè)結(jié)構(gòu)體定義如下:

typedefstruct_UNICODE_STRING{USHORTLength;//字符串的長(zhǎng)度(字節(jié)數(shù))USHORTMaximumLength;//字符串緩沖區(qū)的長(zhǎng)度(字節(jié)數(shù))

PWSTRBuffer;//字符串緩沖區(qū)

}UNICODE_STRING,*PUNICODE_STRING;需要注意的是,當(dāng)我們定義了一個(gè)UNICODE_STRING變量之后,它的Buffer域還沒有分配空間,因此我們不能直接賦值,好的做法是使用微軟提供的Rtl系列函數(shù)。

UNICODE_STRINGstr;RtlInitUnicodeString(&str,L"myfirststring!");或者如下所示:

#include<ntdef.h>UNICODE_STRINGstr=RTL_CONSTANT_STRING(L"myfirststring!");UNICODE字符串并不是以“\0”來表示字符串結(jié)束的,而是依靠UNICODE_STRING的Length域來確定。在驅(qū)動(dòng)開發(fā)的過程中,可能遇到很多不同開頭的函數(shù),如前面遇到過的Rtl和Io系列,此外還有比如Ex、Ps、Nt等等。常見的函數(shù)開頭及其含義如下表所示。內(nèi)核模式下各種開頭函數(shù)區(qū)別NativeAPI從用戶模式穿越進(jìn)入到內(nèi)核模式調(diào)用系統(tǒng)服務(wù),這個(gè)穿越過程是通過軟中斷的方式進(jìn)入的。這個(gè)軟中斷的實(shí)現(xiàn)方法在不同版本的Windows實(shí)現(xiàn)方式略有不同,在Win2K下是通過“int2eh”實(shí)現(xiàn)的,在WinXP是通過“sysenter”指令完成的。

軟中斷會(huì)將NativeAPI的參數(shù)和系統(tǒng)服務(wù)號(hào)的參數(shù)一起傳進(jìn)內(nèi)核模式,不同的NativeAPI會(huì)對(duì)應(yīng)不同的系統(tǒng)服務(wù)號(hào),這個(gè)過程是由SSDT輔助完成的。

系統(tǒng)服務(wù)函數(shù)一般和NativeAPI具有相同的名字,例如都是NtCreateFile,但它們的實(shí)現(xiàn)不同,系統(tǒng)服務(wù)調(diào)用是在“ntoskrnl.exe”導(dǎo)出的。

示例程序關(guān)系在驅(qū)動(dòng)中使用鏈表內(nèi)存的分配與釋放設(shè)備驅(qū)動(dòng)分層使用LISTENTRY設(shè)備驅(qū)動(dòng)內(nèi)存的分配與釋放傳統(tǒng)的C語(yǔ)言中,分配內(nèi)存常常使用的函數(shù)是malloc,但在驅(qū)動(dòng)開發(fā)過程中這個(gè)函數(shù)不再有效。驅(qū)動(dòng)中分配內(nèi)存,常用的是調(diào)用ExAllocatePoolWithTag或ExAllocatePool。

//定義一個(gè)內(nèi)存分配標(biāo)記

#defineMEM_TAG‘MyTt’//目標(biāo)字符串,接下來它需要分配空間。

UNICODE_STRINGdst={0};//分配空間給目標(biāo)字符串。根據(jù)源字符串的長(zhǎng)度。dst.Buffer=(PWCHAR)ExAllocatePoolWithTag(NonpagedPool,src->Length,MEM_TAG);if(dst.Buffer==NULL){//錯(cuò)誤處理status=STATUS_INSUFFICIENT_RESOUCRES;

}dst.Length=dst.MaximumLength=src->Length;ExAllocatePoolWithTag的第一個(gè)參數(shù)NonpagedPool表明分配的內(nèi)存是非分頁(yè)內(nèi)存,這樣它們可以永遠(yuǎn)存在于物理內(nèi)存,而不會(huì)被分頁(yè)交換到硬盤上去;第二個(gè)參數(shù)是長(zhǎng)度;第三個(gè)參數(shù)是一個(gè)所謂的“內(nèi)存分配標(biāo)記”。Windows內(nèi)核提供了一個(gè)雙向鏈表結(jié)構(gòu)LIST_ENTRY,此外還有一些其他的結(jié)構(gòu),比如SINGLE_LIST_ENTRY(單向鏈表).LIST_ENTRY是一個(gè)雙向鏈表結(jié)構(gòu),但直接使用它將毫無任何意義,通常的做法是自定義一個(gè)結(jié)構(gòu)體,將LIST_ENTRY作為該結(jié)構(gòu)體的一個(gè)子域,這樣給予了大限度的靈活性,因?yàn)閿?shù)據(jù)需求千差萬(wàn)別,只要簡(jiǎn)單修改一下便可利用LIST_E

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論