OK論壇

 找回密碼
 註冊
查看: 1549|回復: 0

Windows NT Device Drivers

 關閉 [複製鏈接]
  • TA的每日心情
    開心
    2015-8-6 04:09 AM
  • 簽到天數: 159 天

    連續簽到: 1 天

    [LV.7]常住居民III

    發表於 2009-8-25 23:59:56 | 顯示全部樓層 |閱讀模式
    本書中的樣例程式都是 Windows NT 內核模式設備驅動程式。本章介紹構建驅動程式以及理解本書樣例所需的資訊。但是本章可不是驅動程式大全,詳盡討論驅動程式的最好的資訊來源就是 Art Baker 所著的 TheWindows NT Device Driver Book: A Guide for Programmers 和 Windows NT DeviceDriver Kit (DDK) 所帶的文檔。


    PREREQUISITES TO WRITING NT DEVICE DRIVERS

    要建立 Windows NT 內核模式驅動程式開發環境,必須安裝以下工具軟體:

    Windows NT Device Driver Kit (DDK) from Microsoft 為進行設備驅動的開發,需要安裝 DDK 。DDK包含開發設備驅動所需的頭檔、庫和工具。

    32-bit compiler 要編譯設備驅動還需要32位元的編譯器。我們強烈推薦使用微軟的編譯器來構建本書的樣例。

    Win32 Software Development Kit (SDK) 儘管編譯本書的樣例不需要,但我們還是推薦你安裝上最新版本的
    Win32 SDK。 而且,在用 DDK 工具構建設備驅動時,還應將環境變數 MSTOOLS 設為 Win32 SDK 所安裝的位置。沒安裝 Win32 SDK的話可以在控制面板裏的“系統”程式中添加此環境變數來蒙混系統,讓它以為已經安裝了。


    DRIVER BUILD PROCEDURE

    Windows NT 4.0 Device Driver Kit 安裝後在開始功能表加入了四個快捷方式:Free BuildEnvironment、Checked Build Environment、DDK Help 和 Getting Started. Free BuildEnvironment 和 Checked Build
    Environment 快捷方式都指向一個叫 SETENV.BAT 的批次檔案,但命令行參數不同。假設 DDK 安裝在目錄
    E:\DDK40 下,則 Free Build Environment 快捷方式使用以下命令:

    %SystemRoot%\System32\cmd.exe /k E:\DDK40\bin\setenv.bat E:\DDK40 free

    而 Checked Build Environment 快捷方式使用以下命令:

    %SystemRoot%\System32\cmd.exe /k E:\DDK40\bin\setenv.bat E:\DDK40 checked

    兩個快捷方式都啟動了 CMD.EXE 並使其執行帶有相應參數的 SETENV.BAT 文件。因為有 /k 開關,命令執行完後
    CMD.EXE 仍然在運行。SETENV.BAT 設置了環境變數,這些變數都加到了 CMD.EXE 進程的環境變數列表裏。 DDK
    的工具都靠 CMD.EXE 來運行,因此就可以使用這些環境變數。SETENV.BAT所設定的環境變數有:BUILD_DEFAULT、BUILD_DEFAULT_TARGETS、BUILD_MAKE_PROGRAM 和 DDKBUILDENV。

    驅動程式都是用一個由 DDK 提供的叫 BUILD.EXE 的工具程式編譯的。此程式以一個名為 SOURCES 的檔作為輸入。SOURCES檔中包含著目標可執行檔的檔案名、目標可執行檔的類型(比如是 DRIVER 還是 PROGRAM)和要創建的可執行檔的路徑。

    DDK 自帶的樣例設備驅動程式中都有一個 makefile。然而,那可不是樣例驅動的真正的 makefile。 樣例驅動的
    makefile 都只是包含進一個共有的 makefile,MAKEFILE.DEF。這個 MAKEFILE.DEF 保存在 DDK 安裝目錄的 INC
    目錄中。

    以下是一個 DDK 樣例的 makefile:

    #
    # DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
    # file to this component. This file merely indirects to the real make file
    # that is shared by all the driver components of the Windows NT DDK
    #

    !INCLUDE $(NTMAKEENV)\makefile.def

    本書中的一些驅動樣例含有組合語言文件(.ASM 文件)。直接在 SOURCES 檔裏指定 .ASM 檔是不行的,必須創建一個名為 I386的目錄存放根源程式檔。所有 .ASM 檔都必須放在 I386 目錄下。BUILD.EXE 會自動用
    ML.EXE 編譯這些 .ASM 文件。

    按照 SOURCES 檔指定的設置和平臺相關的環境變數,BUILD.EXE 就生成了驅動程式或是應用程式。若在構建過程中遇到錯誤,就記錄在一個叫BUILD.ERR 的文件裏。若有警告,則記錄在 BUILD.WRN 文件裏。 BUILD 還會生成一個 BUILD.LOG 檔,它記錄著 BUILD所使用的命令列表和命令返回的資訊。


    STRUCTURE OF A DEVICE DRIVER

    正如每一個 Win32 應用程式都有一個入口點(main/WinMain)一樣,每個內核模式驅動也都有個入口點,叫作DriverEntry. 一個叫SYSTEM 的特殊進程負責載入這些驅動。在系統中,每個驅動都由一個設備名代表,這樣每一個驅動都必須為其設備創建一個設備名。這項工作是靠IoCreateDevice 函數完成的。若 Win32 函數需要打開設備驅動的控制碼,驅動還需要在 DosDevices物件目錄下為設備創建一個符號鏈結。這又是靠調用
    IoCreateSymbolicLink 函數來完成的。 一般來說,都在驅動的 DriverEntry函數裏為設備創建設備物件和符號鏈結物件並做一些驅動程式的或是與驅動相關的初始化。

    本書的大多數設備驅動樣例都是偽設備驅動。這些驅動並不控制任何的物理設備,而是用來完成只能由設備驅動才能完成的工作(設備驅動工作在處理器的最高優先順序模式——Intel 處理器的 Ring 0)。另外,DriverEntry
    提供其他函數的入口點,比如 OPEN、 CLOSE、DEVICEIOCONTROL 等等。 提供入口點就是向 device object的一些域添加函數指標,而 device object 又是傳遞給 DriverEntry 的一個參數。

    因為本書的大多數設備驅動樣例都是偽設備驅動,所以 DriverEntry函數都是一樣的。只有與驅動相關的初始化是不同的。我們沒有在每個驅動樣例中都重複相同的代碼,而是使用了一個宏。這個宏叫做 MYDRIVERENTRY:

    #define MYDRIVERENTRY(DriverName, DeviceId, DriverSpecificInit) \
    PDEVICE_OBJECT deviceObject = NULL; \
    NTSTATUS ntStatus; \
    WCHAR deviceNameBuffer[] = L"\\Device\\"##DriverName; \
    UNICODE_STRING deviceNameUnicodeString; \
    WCHAR deviceLinkBuffer[] = L"\\DosDevices\\"##DriverName; \
    UNICODE_STRING deviceLinkUnicodeString; \
    \
    RtlInitUnicodeString (&deviceNameUnicodeString, deviceNameBuffer); \
    ntStatus = IoCreateDevice (DriverObject, \

    0, \

    &deviceNameUnicodeString, \

    ##DeviceId, \

    0, \

    FALSE, \

    &deviceObject \

    ); \
    \
    if (NT_SUCCESS(ntStatus)) { \
    RtlInitUnicodeString (&deviceLinkUnicodeString, deviceLinkBuffer);\
    ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString, \

    &deviceNameUnicodeString);\
    if (!NT_SUCCESS(ntStatus)) {\
    IoDeleteDevice (deviceObject); \
    return ntStatus; \
    } \
    \
    ntStatus=##DriverSpecificInit; \
    \
    if (!NT_SUCCESS(ntStatus)) {\
    IoDeleteDevice (deviceObject); \
    IoDeleteSymbolicLink(&deviceLinkUnicodeString); \
    return ntStatus; \
    } \
    \
    \
    DriverObject->MajorFunction[IRP_MJ_CREATE] = \
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = \
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DriverDispatch; \
    DriverObject->DriverUnload = DriverUnload; \
    return STATUS_SUCCESS; \
    } else { \
    return ntStatus; \
    };

    這個宏使用以下三個參數:
    .第一個參數是驅動名,用來創建設備名和符號鏈結名。
    .第二個參數是設備 ID,用來唯一標識設備。
    .第三個參數是函數名,包含驅動相關的初始化。

    這個巨集擴展後會調用所需的函數,如 IoCreateDevice 和 IoCreateSymbolicLink。若成功,驅動調用由第三個參數指定的驅動相關的初始化函數。若成功,此宏就向 DriverObject 中填入驅動提供的其他函數的指標。一旦在DriverEntry 中使用了此巨集,就需要編寫 DriverDispatch和 DriverUnload 函數,因為此巨集引用了這些函數。

    此巨集的定義可在配套光碟中的 UNDOCNT.H 裏找到。

    對驅動程式的所有請求都是以 I/O Request packet (IRP) 的形式發送的。 驅動程式希望系統通過 DriverEntry
    裏填入的函數指標來為所有的驅動請求調用相應的驅動程式函數。 今後的討論中我們假定所有的驅動程式函數指標都指向 DriverDispatch 函數。

    當應用程式用 CreateFile API 打開一個 device driver 的控制碼時,調用 DriverDispatch 函數所用的參數 IRP
    包含著 IRP_MJ_CREATE 的命令代碼。當應用程式調用 CloseHandle API 函數關閉 device driver 控制碼時,這個
    IRP 就包含著 IRP_MJ_CLOSE 命令代碼。當應用程式調用 DeviceIoControl API 函數與設備交換資料時,此 IRP
    包含著 IRP_MJ_DEVICE_CONTROL 命令代碼。 若驅動程式被多個進程使用,則可以使用 CREATE 和 CLOSE 入口點來完成進程各自的初始化

    因為所有的 IRP 都要經過 DriverDispatch,就需要有一種方法來區分實際所請求的函數。通過 I/O Request
    Packet (IRP) 的 MajorFunction 域就是幹這個的。request packet中有用來完成請求所需的函數代號和其他的參數。當從系統中卸載驅動時,就會調用 DriverUnload 函數。與 DriverUnload相同,DriverUnload 函數也是在 SYSTEM 進程上下文中調用的。一般來說,在 DriverUnload 函數裏,驅動程式刪除由DriverEntry 創建的符號鏈結和設備名,並完成一些驅動相關的反初始化。


    SUMMARY

    在這一章裏,我們講到了構建 Windows NT 設備驅動程式的軟體要求,構建驅動程式的過程以及一個典型驅動的的結構。之後我們還解釋了一個簡單的巨集,這個巨集可以為一般驅動的生成入口代碼。

     
    回復

    使用道具 舉報

    您需要登錄後才可以回帖 登錄 | 註冊

    本版積分規則

    Archiver|手機版|小黑屋|OK討論區

    GMT+8, 2025-6-24 03:31 PM , Processed in 0.057283 second(s), 19 queries , Gzip On.

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

    快速回復 返回頂部 返回列表