日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

[Windows驱动开发](三)基础知识——驱动例程

發布時間:2024/4/11 windows 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Windows驱动开发](三)基础知识——驱动例程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、NT式驅動的基本例程

1. 驅動入口函數——DriverEntry

[cpp]?view plaincopy
  • //?驅動程序的一般性定義??
  • ??
  • NTSTATUS?DriverEntry(IN?PDRIVER_OBJECT?pDriverObject,?IN?PUNICODE_STRING?pRegistryPath);??
  • ??
  • //???

  • DriverEntry的主要工作是對驅動程序進行初始化。它由系統進程System調用的。

    驅動被加載的時候會創建一個驅動對象,查詢此驅動程序對應的注冊表項。

    DriverEntry被調用的時候會傳進兩個參數。他們分別是剛才創建的驅動對象的指針和指向設備服務鍵的鍵名字符串指針。這個字符串的內容一般是\RESGISTRY\MACHINE\SYSTEM\ControlSet\Services\[服務名]。在驅動程序中,字符串一般以UNICODE形式存在:

    注:設備服務鍵的鍵名有時候需要保存下來,當函數返回的時候此值可能會被清空。

    DriverEntry等內核函數的返回值一般是NTSTATUS類型的。使用宏NT_SUCCESS(NTSTATUS status)可檢測返回狀態是否成功。

    在DriverEntry中,一般需要做一下幾件事情:

    a. 設置驅動卸載例程

    b. IRP的派發函數

    c. 創建設備對象

    其中,驅動卸載例程與IRP派發函數都是對驅動對象設置的。設備對象中有一個MajorFunction數字,用來存放哥哥IRP派發函數的函數指針。

    在NT式驅動中,創建設備對象可以調用IoCreateDevice:

    [cpp]?view plaincopy
  • //?IoCreateDevice在WDK中的定義??
  • ??
  • NTKERNELAPI??
  • NTSTATUS??
  • IoCreateDevice(??
  • ????__in??PDRIVER_OBJECT?DriverObject,??
  • ????__in??ULONG?DeviceExtensionSize,??
  • ????__in_opt?PUNICODE_STRING?DeviceName,??
  • ????__in??DEVICE_TYPE?DeviceType,??
  • ????__in??ULONG?DeviceCharacteristics,??
  • ????__in??BOOLEAN?Exclusive,??
  • ????__out??
  • ????__drv_out_deref(??
  • ????????__drv_allocatesMem(Mem)??
  • ????????__drv_when((((inFunctionClass$("DRIVER_INITIALIZE"))??
  • ?????????????||(inFunctionClass$("DRIVER_DISPATCH")))),??
  • ?????????????__drv_aliasesMem)??
  • ????????__on_failure(__null))??
  • ????PDEVICE_OBJECT?*DeviceObject??
  • ????);??
  • ??
  • //??

  • DriverObject:當前驅動對象指針。

    DeviceExtensionSize:設備擴展的大小。IO管理器會根據這個大小在內存中創建設備擴展,并與驅動對象關聯。

    DeviceName:設備對象的名稱。

    DeviceCharacteristics:設備對象的特征。

    Exclusive:設備對象是否為內核模式下使用,一般固定為TRUE。

    DeviceObject:創建好的設備對象指針。

    注:設備名稱字符串必須是\Device\[設備名]的形式。


    讓用戶態的應用程序能識別設備一般有兩種方法:

    a.?符號鏈接 b. 設備接口(在NT式驅動很少使用)

    符號鏈接可以理解為設備對象在用戶態的名稱。即:設備名稱在內核態使用,符號鏈接在用戶態使用。

    創建符號鏈接可以使用IoCreateSymbolicLink:

    [cpp]?view plaincopy
  • //?IoCreateSymbolicLink在WDK中的定義??
  • ??
  • NTKERNELAPI??
  • NTSTATUS??
  • IoCreateSymbolicLink(??
  • ????__in?PUNICODE_STRING?SymbolicLinkName,??
  • ????__in?PUNICODE_STRING?DeviceName??
  • ????);??
  • ??
  • //??

  • SymbolicLinkName:符號鏈接名。

    DeviceName:設備對象名。

    注:在內核態,符號鏈接是以“\??\”或者“\DosDevices\”開頭的。而在用戶模式下則是以“\\.\”開頭的。


    設備擴展在被使用時可使用如下的代碼:

    [cpp]?view plaincopy
  • //?Code:使用設備擴展??
  • ??
  • PDEVICE_EXTENSION?pDeviceExtension?=?(PDEVICE_EXTENSION)pDeviceObject->DeviceExtension;??
  • ??
  • //???

  • 2.?驅動卸載例程——DriverUnload

    此例程在驅動卸載的時候被調用。在NT式驅動里面負責刪除在DriverEntry中創建的設備對象,并且刪除與其相關聯的符號鏈接。同時還負責某些資源的回收工作。

    刪除設備對象的函數是IoDeleteDevice

    [cpp]?view plaincopy
  • //?IoDeleteDevice在WDK中的定義??
  • ??
  • NTKERNELAPI??
  • VOID??
  • IoDeleteDevice(??
  • ????__in?__drv_mustHold(Memory)?__drv_freesMem(Mem)?PDEVICE_OBJECT?DeviceObject??
  • ????);??
  • ??
  • //??

  • DeviceObject:要被刪除的設備對象指針。


    刪除符號鏈接的函數是IoDeleteSymbolicLink

    [cpp]?view plaincopy
  • //?IoDeleteSymbolicLink在WDK中的定義??
  • ??
  • NTKERNELAPI??
  • NTSTATUS??
  • IoDeleteSymbolicLink(??
  • ????__in?PUNICODE_STRING?SymbolicLinkName??
  • ????);??
  • ??
  • //??
  • SymbolicLinkName:已經被注冊的、待刪除的符號鏈接。


    根據驅動對象可以遍歷所有由該驅動創建的設備對象。通過驅動對象的DeviceObject域可以找到驅動對象的第一個設備,然后根據設備對象的NextDevice域,就可以找到設備鏈表中其他的設備對象。


    二、WDM式驅動的基本例程

    //

    在WDM模型中,一個設備的操作至少需要兩個設備對象共同來完成。一個是物理設備對象(Physical Device Object,簡稱PDO),一個是功能設備對象(Function?Device?Object,簡稱FDO)。當計算機插入某個設備的時候,總線驅動會自動創建PDO。PDO不能單獨操作設備,必須與FDO一起使用。當Windows提示要安裝驅動的時候,實際上安裝的是WDM驅動程序,負責創建FDO,并附加到PDO上。

    當一個FDO附加在PDO的時候,PDO的AttachedDevice會記錄FDO的位置。PDO是底層驅動(下層驅動),FDO是高層驅動(上層驅動)。

    在FDO與PDO之間還會存在過濾驅動。在FDO上面的叫做上層過濾驅動,在FDO下層的叫做下層過濾驅動。一個WDM驅動可以有很多個上層過濾驅動和下層過濾驅動。設備對象的StackSize子域表明該設備對象到最下層的物理設備中間還存在的設備對象數。

    1.?WDM驅動的入口函數——DriverEntry

    和NT式驅動一樣,WDM驅動的入口程序也是DriverEntry。但是創建設備對象的功能并不在DriverEntry中執行,而是交給了新的例程——AddDevice;同時增加了對IRP_MJ_PNP處理的派發函數。

    AddDevice例程是WDM特有的,在DriverEntry中需要設置AddDevice例程的函數地址。設置的方式是在驅動對象的DriverExtension子域的AddDevice子域保存AddDevice實際例程的函數地址。AddDevice例程的名字可以隨意命名。

    [cpp]?view plaincopy
  • //?AddDevice函數聲明??
  • NTSTAUS?MyAddDevice(IN?PDRIVER_OBJECT?pDriverObject,?IN?PDEVICE_OBJECT?PhysicalDeviceObject)??
  • ??
  • //?設置AddDevice實際例程的地址??
  • pDriverObject->DriverExtension->?AddDevice?=?MyAddDevice;??
  • ??
  • //??
  • 2.?驅動卸載例程——DriverUnload()

    在WDM驅動中,實際的卸載工作被IRP_MN_REMOVE_DEVICE對應的派發函數處理了,這里的DriverUnload主要處理在DriverEntry中申請的內存。
    ? ? a.?IRP_MN_REMOVE_DEVICE處理 ? ? 驅動橫須內部是由IRP驅動的,IRP_MN_REMOVE_DEVICE這個IRP是當設備需要被卸載的時候,由即插即用管理器創建,并發送到驅動程序中的。IRP一般由兩個號碼指定該IRP的具體意義,一個是主IRP號(Major IRP),一個是輔IRP號(Minor IRP)。 ? ? 當設備需要被卸載的時候,會先后發出多個IRP_MJ_PNP。這些IRP的輔IRP號會有所不同。其中之一的IRP_MN_REMOVE_DEVICE。 ? ? 在WDM驅動程序中,對設備的卸載一般是在對IRP_MN_REMOVE_DEVICE的出口函數中進行卸載。其除了需要刪除學部,取消符號鏈接外,還需要將FDO從PDO的堆棧中移除。需要調用IoDetachDevice: [cpp]?view plaincopy
  • //?IoDetachDevice在WDK中的定義:??
  • ??
  • NTKERNELAPI??
  • VOID??
  • IoDetachDevice(??
  • ????__inout?PDEVICE_OBJECT?TargetDevice????//?下層堆棧上的設備對象??
  • ????);??
  • ??
  • //???
  • 此時,FDO從設備鏈上刪除,但是PDO還在。PDO由操作系統負責刪除。



    AddDevice基本步驟: 1. AddDevice通過IoCreateDevice函數創建FDO,創建FDO的符號鏈接 2. 在驅動設備擴展保存剛才創建的FDO的地址。 3. 調用IoAttachDeviceToDeviceStack()將FDO附加到PDO上。 [cpp]?view plaincopy
  • //?IoAttachDeviceToDeviceStack在WDK中的定義??
  • ??
  • NTKERNELAPI??
  • PDEVICE_OBJECT??
  • IoAttachDeviceToDeviceStack(??
  • ????__in?__drv_mustHold(Memory)?__drv_when(return!=0,?__drv_aliasesMem)??
  • ????PDEVICE_OBJECT?SourceDevice,??
  • ????__in?PDEVICE_OBJECT?TargetDevice??
  • ????);??
  • ??
  • //??
  • SourceDevice:FDO附加在PDO上時,這個參數代表FDO。 TargetDevice:被附加的設備。如果在FDO與PDO之間存在過濾驅動,則FDO實際上是附加在過濾驅動上的,過濾驅動則附加在PDO上。 返回值:返回SourceDevice的下層設備。


    [cpp]?view plaincopy
  • //?根據上面的一個設備擴展定義??
  • ??
  • typedef?struct?_DEVICE_EXTENSION??
  • {??
  • ????PDEVICE_OBJECT?pFunctionDeviceObject;??//?設備對象(FDO)??
  • ????UNICODE_STRING?ustrDeviceName;?????????//?設備名稱??
  • ????UNICODE_STRING?ustrSymbolicLinkName;???//?符號鏈接名??
  • ??
  • ????PDEVICE_OBJECT?pNextStackDevice;???????//?下一個設備對象(FDO)的地址??
  • }?DEVICE_EXTENSION,?*PDEVICE_EXTENSION;??
  • ??
  • ??
  • //???

  • 4. 設置設備擴展pFunctionDeviceObject->Flags。 ? ? DO_BUFFERED_IO:緩沖內存設備 ? ? ~DO_DEVICE_INITIALIZING:這個必須設置,表示完成Flags的初始化。

    總結

    以上是生活随笔為你收集整理的[Windows驱动开发](三)基础知识——驱动例程的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。