Windows驅動程序設計入門.ppt
《Windows驅動程序設計入門.ppt》由會員分享,可在線閱讀,更多相關《Windows驅動程序設計入門.ppt(49頁珍藏版)》請在裝配圖網(wǎng)上搜索。
Windows驅動程序設計入門,2,Windows的虛擬內存管理,3,Windows的虛擬內存管理,Windows的虛擬內存管理機制為應用程序和驅動程序提供了兩種服務:使每個進程都擁有自己獨立的內存地址空間;對于32位Windows而言,每個任務可尋址的內存地址空間都為0 x00000000~0 xFFFFFFFF(232,4GB)當物理內存不夠4GB時,虛擬內存管理模塊會用磁盤空間模擬內存空間,并且該模擬過程對應用程序是透明的。,4,用戶地址空間與內核地址空間,Windows將每個進程的4GB的獨立地址空間又劃分為用戶地址空間(0 x00000000~0 x7FFFFFFF)和內核地址空間(0 x80000000~0 xFFFFFFFF)兩部分。操作系統(tǒng)內核代碼和數(shù)據(jù)存放在內核地址空間;每個進程自己私有的代碼和數(shù)據(jù)存放在用戶地址空間雖然Windows的內核代碼和數(shù)據(jù)被映射到了每個進程的地址空間中(所有進程看到的內容是相同的),但在實際的物理內存中,只有內核代碼和數(shù)據(jù)的一份拷貝。,5,用戶地址空間與內核地址空間,6,用戶模式與內核模式,為了更好地保護系統(tǒng),Windwos規(guī)定了兩種處理器工作模式:用戶模式和內核模式。工作在用戶模式的程序只能使用CPU支持指令集的一個子集,只能訪問用戶空間中的內存,并且不能直接訪問硬件。工作在內核模式的程序不受任何限制,可以使用CPU支持的任意指令,可以訪問任意的內存空間,可以直接訪問硬件。所有的Windows應用程序都工作于用戶模式,Windows內核程序都工作于內核模式。也可以認為:位于用戶空間的代碼都工作于用戶模式,位于內核空間的代碼都工作于內核模式。應用程序只能通過Windows規(guī)定的一些API訪問內核模式的代碼和數(shù)據(jù)。,7,Windows系統(tǒng)結構,8,什么是Windows驅動程序?,Windows驅動程序是一種位于內核地址空間并且工作于內核模式的一種特殊的程序類型(.sys文件)。驅動程序是操作系統(tǒng)信任的一個內核擴展模塊。驅動程序和操作系統(tǒng)之間遵循的是容器與插件模型。OS負責管理Driver的生命周期;Driver是一種被動的軟件模塊。驅動程序類似于DLL程序,它是一個回調函數(shù)(子程序)的集合體,這些函數(shù)由OS在適當?shù)臅r候調用驅動程序也可以通過Windows內核API獲得OS的一些服務。,9,編驅動程序用什么編程語言?,C語言C++語言%1的情況下會用到匯編語言目前還不能用其它高級語言編寫驅動程序。,10,編驅動程序用什么開發(fā)工具?,WDK(WindowsDriverKit)(可以到微軟網(wǎng)站上免費下載)DriverStudio(CompuwareNuMega公司的產(chǎn)品)+DDKWinDriver+DDK,11,WDK中包含什么?,與Windows內核API函數(shù)相關的頭文件(如ddk.h,wdm.h等)與Windows內核API函數(shù)相關的導入庫(wdm.lib等)內核專用C運行時間庫的頭文件和導入庫關于驅動程序編程模型和內核API函數(shù)的幫助文檔C++編譯器和鏈接器,綜合創(chuàng)建工具內核調試工具、分析工具,12,內核模式下我們能調用哪些函數(shù)?,Windows內核輸出的內核API函數(shù);WDK提供的運行時間庫其它驅動程序提供的服務,13,內核模式下我們不能調用哪些函數(shù)?,Windows的用戶模式API函數(shù);ISO規(guī)定的C/C++標準函數(shù)庫,14,最簡單的NT式驅動程序,extern“C”{#include}extern"C"NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegistryPath){NTSTATUSstatus=STATUS_UNSUCCESSFUL;/*KdPrint將輸入字符串發(fā)送到一個特殊內存區(qū),利用DbgView工具可以觀察該內存區(qū)的內容*/KdPrint(("HelloWorld!!!!"));returnstatus;},15,關于最簡單驅動的問題,第一個extern“C”的作用是什么?第二個extern“C”的作用是什么?typedeflongNTSTATUS;#defineIN#ifdefDBG#defineKdPrint(a)DbgPrint##a#else#defineKdPrint(a)#endif,16,驅動程序的入口函數(shù),NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegistryPath){…………returnstatus;},參數(shù)DriverObject表示指向驅動對象的指針;參數(shù)RegistryPath表示該驅動所對應的注冊表服務鍵的子目錄返回值表示初始化是否成功,17,DDK中一個驅動型工程的組成,MAKEFILE文件,一般不作改動Sources文件:(1)指示了整個工程由哪些源程序和資源文件構成;(2)包含了主要的編譯參數(shù),指導編譯器和鏈接器的工作。.cpp文件和.h文件如何build驅動工程?用DDK中的build工具。build工具會根據(jù)MAKEFILE文件和Sources文件以及相關環(huán)境變量的指示編譯并鏈接工程中的.cpp文件和.h文件,18,如何安裝NT型驅動程序?,方法1:在注冊表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services下增加一個新的項目??梢詫⒃摲罩付殚_機自啟動,也可以指定為按需啟動。如果是按需啟動,則可以用netstart命令啟動,用netstop命令停止。方法2:編寫另外的用戶模式程序利用SCM函數(shù)按需啟動。方法3:在調試階段可以利用第三方的工具如:DriverMoniter和IntallDriver隨時安裝和卸載。,19,如何調試驅動程序?,方法1:打印調試信息。即用DbgPrint函數(shù)打印調試信息,然后在驅動運行時用Dbgview等工具觀察這些信息。方法2:分析內存轉儲(dump)文件。方法3:使用WinDbg、SoftICE等高級調試工具。,20,用WinDbg+VMWare進行雙機調試,Step1:安裝WinDbg和VMWare,并在VMWare中安裝好WindowsXP。Step2:設置好WMWare的虛擬串口Step3:將虛擬機中的WindowsXP設置為調試運行模式。(修改boot.ini文件)Step4:以調試方式啟動虛擬機中的WindowsXPStep5:啟動WinDbgStep6:設置WinDbg的Symbol文件路徑,設置C源程序路徑。Step7:設置斷點,監(jiān)視變量,21,HelloWorld版的WDM驅動程序,extern“C”{#include“wdm.h”}extern"C"NTSTATUSDriverEntry(INPDRIVER_OBJECTDriverObject,INPUNICODE_STRINGRegistryPath){NTSTATUSstatus=STATUS_DEVICE_CONFIGURATION_ERROR;KdPrint(("HellowWorld!!!!"));returnstatus;},22,如何安裝WDM驅動程序?,必須編寫一個安裝指示文件(.inf)指導Windows將驅動程序安裝到指定位置(一般安裝在windows\system32\drivers子目錄下),并在注冊表中進行登記。對于即插即用類設備的驅動,操作系統(tǒng)會自動發(fā)現(xiàn)該設備并調用“添加新硬件”程序向用戶詢問相應的inf文件的位置。對于非即插即用類設備的驅動,用戶必須自己手動調用“添加新硬件”程序,并通過告訴該程序inf文件的位置。,23,inf文件主要包含了哪些內容?,設備類型、設備型號、廠商信息、程序版本號…。對操作系統(tǒng)版本和CPU類型的要求…源文件(.sys文件)的文件名和所在位置安裝目標子目錄在注冊表中添加哪些內容硬件配置信息安全配置信息,24,驅動對象(DriverObject),在操作系統(tǒng)首次裝載一個驅動程序之后,它會創(chuàng)建一個數(shù)據(jù)結構用來記錄該驅動,該數(shù)據(jù)結構我們稱為驅動對象(DriverObject)。驅動對象記錄與驅動程序本身相關的信息,它主要包含了除了DriverEntry之外的其它驅動程序入口函數(shù)的入口地址。(驅動程序是一種具有多個入口函數(shù)的程序)驅動對象是由操作系統(tǒng)創(chuàng)建,然后作為DriverEntry的第一個參數(shù)傳遞給你的程序。在獲得驅動對象的指針之后,你的程序需要對其中的一些字段進行初始化。,25,驅動對象(DriverObject),驅動對象在DDK的頭文件(ntddk.h)中按如下方式定義:。,typedefstruct_DRIVER_OBJECT{CSHORTType;CSHORTSize;……}DRIVER_OBJECT,*PDRIVER_OBJECT;,由上面的定義可以看成,驅動對象不同于C++中的Class,它只是一個Struct。,26,,27,驅動對象的一些關鍵字段(一),DriverStartIo(PDRIVER_STARTIO):指向StartIO入口函數(shù)的指針.DriverUnload(PDRIVER_UNLOAD):指向DriverUnload入口函數(shù)的指針。在驅動程序被從內存中卸載時,DriverUnload入口函數(shù)會被操作系統(tǒng)調用,你應該在該函數(shù)內部做一些與DriverEntry向對應的資源清除工作。MajorFunction(一個數(shù)組,數(shù)組中每一元素又是一個指向函數(shù)的指針PDRIVER_DISPATCH):數(shù)組中每一個指針指向一個入口函數(shù)。在接收到不同的請求包(IRP)時,OS會調用不同的入口函數(shù)。,28,驅動對象的一些關鍵字段(二),DeviceObject(PDEVICE_OBJECT):指向一個鏈表的指針,該鏈表中每一個節(jié)點都存儲了一個FDO對象。每一個FDO都代表一個由該驅動維護的硬件設備實例。在WDM模型中,該鏈表由OS自動維護。DriverExtension(PDRIVER_EXTENSION):指向另外一個結構體,該結構體中唯一有用的字段為AddDevice。AddDevice字段指向一個入口函數(shù)。在操作系統(tǒng)發(fā)現(xiàn)一個新的設備實例時,它會自動調用AddDevice函數(shù),你應該在該函數(shù)中做一些與設備實例相關的初始化工作。,29,DriverEntry函數(shù)的主要工作,在操作系統(tǒng)創(chuàng)建的驅動對象中填寫其它入口函數(shù)的地址,使得操作系統(tǒng)在必要的時候能夠找到這些入口函數(shù)并調用它們。創(chuàng)建一個或多個設備對象,并將這些對象掛接在驅動對象所指示的鏈表上。(只針對NT型驅動)與該設備相關的其他初始化工作,VOID(*PDRIVER_UNLOAD)(INPDRIVER_OBJECTDriverObject);VOID(*PDRIVER_STARTIO)(INPDEVICE_OBJECTDeviceObject,INPIRPIrp);NTSTATUS(*PDRIVER_DISPATCH)(INPDEVICE_OBJECTDeviceObject,INPIRPIrp);NTSTATUS(*PDRIVER_ADD_DEVICE)(INPDRIVER_OBJECTDriverObject,INPDEVICE_OBJECTPhysicalDeviceObject);,30,DriverUnload函數(shù)的主要工作,刪除以鏈表形式掛接在驅動對象上的一個或多個設備對象。(只針對NT型驅動)進行與DriverEntry函數(shù)中相對應的反初始化工作。例如如果在DriverEntry函數(shù)中申請了堆內存,那么在DriverUnload函數(shù)中應該釋放該堆內存。,VOIDDriverUnload(PDRIVER_OBJECTDriverObject){RtlFreeUnicodeString(},31,第二簡單的驅動程序,extern“C”{#include}VOIDHelloDDKUnload(INPDRIVER_OBJECTpDriverObject);NTSTATUSHelloDDKDispatchRoutine(INPDEVICE_OBJECTpDevObj,INPIRPpIrp);extern"C"NTSTATUSDriverEntry(INPDRIVER_OBJECTpDriverObject,INPUNICODE_STRINGpRegistryPath){NTSTATUSstatus=STATUS_SUCCESS;KdPrint(("EnterDriverEntry\n"));KdPrint(("RegistryPath:%wZ\n",pRegistryPath));pDriverObject->DriverUnload=HelloDDKUnload;pDriverObject->MajorFunction[IRP_MJ_CREATE]=HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_CLOSE]=HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_WRITE]=HelloDDKDispatchRoutine;pDriverObject->MajorFunction[IRP_MJ_READ]=HelloDDKDispatchRoutine;KdPrint(("LeaveDriverEntry\n"));returnstatus;},32,第二簡單的驅動程序(續(xù)),VOIDHelloDDKUnload(INPDRIVER_OBJECTpDriverObject){KdPrint(("EnterDriverUnload\n"));KdPrint(("LeaveDriverUnload\n"));}NTSTATUSHelloDDKDispatchRoutine(INPDEVICE_OBJECTpDevObj,INPIRPpIrp){NTSTATUSstatus=STATUS_SUCCESS;KdPrint(("EnterHelloDDKDispatchRoutine\n"));KdPrint(("LeaveHelloDDKDispatchRoutine\n"));returnstatus;},33,設備對象(DeviceObject),針對每一個硬件設備,Windows都需要用一個數(shù)據(jù)結構來記錄它的相關信息,這個數(shù)據(jù)結構就叫做設備對象(DevcieObject)。因為一個驅動程序可以同時管理多個同類型的硬件設備,因此一個驅動對象可以對應多個設備對象。對應同一個驅動對象的多個設備對象構成一個鏈表掛接在驅動對象的DeviceObject字段上。設備對象由驅動程序負責創(chuàng)建和初始化,由操作系統(tǒng)負責保存和管理。設備對象可以有名字,其他驅動程序或應用程序可以通過該名字找到該設備對象。,34,,TheDeviceObject,35,設備對象的一些關鍵字段(一),DriverObject(PDRIVER_OBJECT):指向與該設備對象相對應的驅動對象的指針。NextDevice(PDEVICE_OBJECT):指向下一個設備對象的指針,利用該字段與同一個驅動對象對應的多個設備對象就可以構成一個單鏈表,該鏈表最后掛接在驅動對象的DeviceObject字段上。,36,設備對象的一些關鍵字段(二),Flags(ULONG):保存了一些標志位,這些標志位指示了該設備的一些工作方式。,37,設備對象的一些關鍵字段(三),Characteristics(ULONG):另外一組標志位集合。DeviceExtension(PVOID):指向一個擴展內存區(qū),該內存區(qū)的大小和使用方式由程序員規(guī)定。一般在該區(qū)域存放一個自定義的結構體,用于存儲硬件設備特有的信息。今后稱該結構體為設備擴展對象。該擴展內存區(qū)由操作系統(tǒng)負責創(chuàng)建并維護。DeviceType(DEVICE_TYPE):一個枚舉型變量,指明該設備的類型(FILE_DEVICE_UNKNOWN)AlignmentRequirement(ULONG):指定該設備使用內存時的對齊方式(FILE_BYTE_ALIGNMENT、FILE_WORD_ALIGNMENT…FILE_512_BYTE_ALIGNMENT),38,如何創(chuàng)建設備對象,,利用內核API函數(shù)IoCreateDevice創(chuàng)建設備對象。OS負責申請并管理設備對象所需內存,并對其中的一些字段按照輸入?yún)?shù)做了初始化,最后將其掛接在設備對象鏈表上。,NTSTATUSIoCreateDevice(INPDRIVER_OBJECTDriverObject,//設備對象所對應的驅動對象INULONGDeviceExtensionSize,//設備擴展區(qū)的大小INPUNICODE_STRINGDeviceNameOPTIONAL,//設備對象名稱INDEVICE_TYPEDeviceType,//設備類型INULONGDeviceCharacteristics,//設備對象特征INBOOLEANExclusive,//一般設為FALSEOUTPDEVICE_OBJECT*DeviceObject//由操作系統(tǒng)創(chuàng)建的設備對象//的起始地址利用該參數(shù)返回);,39,如何刪除設備對象,,在WDM驅動中,如果接收到IRP_MN_REMOVE_DEVICE消息,則應刪除設備對象;在NT式驅動中,在DriverUnload函數(shù)中刪除設備對象。在創(chuàng)建設備對象之后如果出錯也應該及時刪除對象。通過調用內核API函數(shù)IoDeleteDevice刪除設備對象,NTSTATUSstatus=IoCreateDevice(...);if(!NT_SUCCESS(status))returnstatus;………….if(){IoDeleteDevice(pdo);returnstatus;},40,設備對象的命名,Windows系統(tǒng)中有一個稱為“對象管理器”的執(zhí)行模塊復雜集中管理系統(tǒng)中所有的內核對象,其中包括驅動對象和設備對象。對象管理器給大多數(shù)內核對象都起了名字,并把這些名字組織為具有樹形結構的命名空間。設備對象一般都位于該命名空間的\Device子目錄下其他內核模塊和驅動程序都可以通過設備的名字獲得該設備對象的指針(利用IoGetDeviceObjectPointer),并通過該指針向驅動對象發(fā)送IRP。用戶模式的應用程序對\Device子目錄沒有訪問權,41,設備對象的命名(續(xù)),為了給自己的設備對象命名,必須將名字存放在一個UNCODE_STRING型的字符串中,并將其作為IoCreateDevice的第3個參數(shù)傳入。,UNICODE_STRINGdevname;RtlInitUnicodeString(,42,設備對象名與符號鏈接,因為應用程序只能訪問Windows內核對象空間中的“\??”子目錄,而對對\Device子目錄沒有訪問權限,因此必須在“\??”子目錄中創(chuàng)建一個符號鏈接,將其指向\Device子目錄中的名字。符號鏈接就類似于Windows文件系統(tǒng)中的快捷方式創(chuàng)建符號鏈接的方法是調用IoCreateSymbolicLink,43,設備對象名與符號鏈接(續(xù)),UNICODE_STRINGdevname;UNICODE_STRINGlinkname;RtlInitUnicodeString(,44,應用程序如何通過設備名打開設備,在用戶模式下“\??”子目錄叫做“\\.\”子目錄,因此通過“\\.\”子目錄下的符號鏈接名就可以找到設備對象,并打開指向設備對象的句柄。,hDevice=CreateFile("\\\\.\\Simple1",GENERIC_WRITE|GENERIC_READ,FILE_SHARE_WRITE|FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);ReadFile(hDevice,lpBuffer,……..);WriteFile(hDevice,lpBuffer,……..);………..,45,創(chuàng)建完設備對象后還需做什么,設置設備擴展對象的內容設置設備對象的flags字段設定該設備的工作方式。,fdo->AlignmentRequirement=….fdo->Flags│=DO_BUFFERED_IO│DO_POWER_PAGABLE;,創(chuàng)建設備對象棧(可選)等所有準備工作做完之后一定要清除flags字段的DO_DEVICE_INITIALIZING標志告訴OS可以接收IRP了,fdo->Flags,46,第三個例子程序,47,基于I/O請求包(IRP)的工作方式,48,應用程序與驅動程序的通信,Windows應用程序與WDM通信的一般過程是:應用程序先用CreateFile函數(shù)打開設備,然后用ReadFile從WDM中讀取數(shù)據(jù),用WriteFile函數(shù)向WDM寫數(shù)據(jù),用DeviceIoControl函數(shù)向WDM發(fā)送自定義的控制信息,最后用CloseHandle函數(shù)關閉設備。對于異步IO請求還可以用CancelIo函數(shù)取消。這些函數(shù)調用使得IO管理器產(chǎn)生相應的IRP發(fā)送給驅動程序,49,第四個例子程序,- 配套講稿:
如PPT文件的首頁顯示word圖標,表示該PPT已包含配套word講稿。雙擊word圖標可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設計者僅對作品中獨創(chuàng)性部分享有著作權。
- 關 鍵 詞:
- Windows 驅動程序 設計 入門
裝配圖網(wǎng)所有資源均是用戶自行上傳分享,僅供網(wǎng)友學習交流,未經(jīng)上傳用戶書面授權,請勿作他用。
鏈接地址:http://m.hcyjhs8.com/p-12668277.html