版權(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 幼兒園云霧主題課程設(shè)計(jì)
- 幼兒環(huán)創(chuàng)課程設(shè)計(jì)分析
- 小班毛豆秋收課程設(shè)計(jì)
- 青島恒星科技學(xué)院《機(jī)器視覺及其程應(yīng)用》2023-2024學(xué)年第一學(xué)期期末試卷
- 小學(xué)平移課程設(shè)計(jì)過程
- 工程概預(yù)算課程設(shè)計(jì)
- 換裝游戲繪畫課程設(shè)計(jì)
- 護(hù)理程序人衛(wèi)版
- 幼兒園vr科技課程設(shè)計(jì)
- 微機(jī)原理課程設(shè)計(jì)計(jì)時(shí)器
- JGJT414-2018 建筑施工模板和腳手架試驗(yàn)標(biāo)準(zhǔn)
- 即興表演智慧樹知到期末考試答案章節(jié)答案2024年上海電影藝術(shù)職業(yè)學(xué)院
- 經(jīng)典廣告解析智慧樹知到期末考試答案章節(jié)答案2024年成都師范學(xué)院
- 汽車行走的藝術(shù)智慧樹知到期末考試答案章節(jié)答案2024年吉林大學(xué)
- 心理學(xué)研究方法 知到智慧樹網(wǎng)課答案
- DZ∕T 0130.13-2006 地質(zhì)礦產(chǎn)實(shí)驗(yàn)室測(cè)試質(zhì)量管理規(guī)范 第13部分:礦石加工選冶性能試驗(yàn)(正式版)
- 系統(tǒng)解剖學(xué)(南方醫(yī)科大學(xué))智慧樹知到期末考試答案章節(jié)答案2024年南方醫(yī)科大學(xué)
- 2023年部編版五年級(jí)數(shù)學(xué)上冊(cè)期末考試卷【含答案】
- 2024年浙江杭州臨安法院編外工作人員招聘筆試參考題庫(kù)附帶答案詳解
- 國(guó)開電大??啤缎姓M織學(xué)》期末考試第二大題多項(xiàng)選擇題庫(kù)(2024版)
- 2024年貴州鐵路投資集團(tuán)有限責(zé)任公司招聘筆試參考題庫(kù)附帶答案詳解
評(píng)論
0/150
提交評(píng)論