windows環境中驅動的開發簡例

摘要:本文介紹了Windows下驅動程序的設計的必要性和基本方法,主要適合於驅動程序的初學者。

一、驅動程序設計的必要性
    在傳統DOS系統下,每個應用程序都有權利讀寫硬件,讀寫I/O端口,控制系統中斷,然而到了Windows系統中,爲了保持良好的系統安全性,對應用程序的權限作出了限制,因爲不適當的硬件讀寫會引發整個系統的崩潰。在Windows系統中,將整個程序設計爲分層結構,其中,應用程序位於ring3,驅動程序位於ring0,應用程序不能讀寫底層硬件,對於硬件操作必須藉助於底層驅動程序,所以,只要是與硬件系統打交道的Windows程序,必然會涉及到驅動程序的開發和設計。

二、驅動程序的分類和設計工具
    驅動程序是Windows系統的內核,驅動程序的分類與Windows相關,在Windows 9X下,驅動程序的類型爲VXD(虛擬設備驅動程序),在Windows 2000/XP,驅動程序的類型爲WDM(Windows驅動程序設計模型),生成的驅動程序設計文件爲.sys格式。
    在Windows9X下,設計驅動程序的工具稱爲VTOOLSD,而在Windows 2000/xp下,設計驅動程序的工具爲DriverStudio中的DriverWorks,另外的設計驅動程序的工具還有WinDriver,微軟提供的開發工具爲Windows DDK。由於所有的驅動設計工具均以DDK作爲基本的類或者參照,加上DDK是一個免費軟件,所以在下面主要以DDK爲例進行講解,掌握了DDK工具,其他工具也就變得簡單了。

三、Window DDK軟件的安裝與環境設置
    每個Windows系統都有各自的DDK開發工具,在安裝DDK前,請先根據Windows系統的不同,安裝不同的DDK工具。在安裝DDK之前,請先安裝相應的編譯器如Visual C++6.0,本文以Windows 2000下的DDK爲例,說明安裝過程,安裝DDK完成後,選擇菜單“開始”->“Development Kit”->“Check Build environment”將自動進行各項環境的設置,當然用戶也可選擇“Free Build environment”,二者的區別在於“check”帶有調試信息,“Free”則不帶有調試信息,一般情況下,在軟件開發階段,選用“check”,而在發佈階段,選用“Free”。
    選擇上述命令後,將進入編譯環境,該環境爲“DOS”界面,進入驅動程序所在的目錄,一般情況下,該目錄包含了以下文件:
makefile 編譯文件,一般不作更改
sources 規定了其中的源文件,驅動程序的類型
源文件 爲.c或者.h文件
    爲了編寫方便,我們可以進入DDK提供的例子下面,將makefile和sources拷貝到我們程序所在的目錄下,將sources進行簡單的修改,編譯時,進入相應的目錄,在該目錄下輸入“Build”,系統編譯完成後,將在objchk\i386目錄下生成相應的.sys文件。

四、驅動程序的編寫
    尋找一個合適的編譯器如EditPlus,當然也可以用VC,只不過需要手動編譯,第一步,找到驅動程序的入口函數DriverEntry(),相當於Main()或者WinMain(),所有的驅動函數入口均從DriverEntry()開始,下面以端口驅動程序爲例,說明驅動的編寫。該文件位於NTDDK\src\general\portio下。
1.創建設備
    對於設備驅動程序,首先要創建該設備,這段代碼可以放在DriverEntry中,也可放在AddDevice中。
首先,調用IoCreateDevice()創建自己的設備,該函數用法可以參考DDK或者相關示例。在端口操作中,可以將函數寫爲:
status = IoCreateDevice (DriverObject,
                    sizeof (LOCAL_DEVICE_INFO),
                    &7,
                    GPD_TYPE,
                    0,
                    FALSE,
                  &deviceObject);
    其次,調用函數IoCreateSymbolicLink()創建兩個設備之間的連接
    status = IoCreateSymbolicLink( &win32DeviceName, &ntDeviceName );
2.初始化所用的資源
    在驅動程序中,總需要訪問I/O端口、系統中斷、內存地址以及DMA,使用這些資源之前,需要獲取資源並且初始化,一種簡單的方法是直接指定,如中斷10,DMA3等,這種方法雖然簡單,但靈活性差,任何硬件資源的改變均需在驅動程序中作出修改;另一種較爲科學的方法就是讓驅動程序訪問註冊表,從註冊表中訪問硬件資源,然後進行初始化。
在驅動程序中,訪問註冊表的函數爲RtlQueryRegistryValues(),該函數的用法較爲複雜,可參考相關資料,建議在驅動程序開始開發時,直接給資源賦值,等驅動程序調試成功後再加入訪問註冊表代碼。
3.註冊驅動程序的各個處理函數
    DriverObject->MajorFunction[IRP_MJ_CREATE]          = GpdDispatch;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = GpdDispatch;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]  = GpdDispatch;
    DriverObject->DriverUnload                          = GpdUnload;
    DriverObject->MajorFunction[IRP_MJ_PNP]            = GpdDispatchPnp;
    DriverObject->MajorFunction[IRP_MJ_POWER]          = GpdDispatchPower;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL]= SystemControl;
    DriverObject->DriverExtension->AddDevice          = GpdAddDevice;
    處理函數的註冊方法有點類似Windows下應用程序設計的消息處理函數,註冊完成後,當處理相應的IRP時,自動調用相應的函數模塊。

五、驅動程序與應用程序間的信息交互
    驅動程序用以訪問底層硬件,應用程序實現人機交互,驅動程序和應用程序之間需要實現相應的信息交互,一方面,應用程序通過對驅動程序發送相應的指令,實現硬件控制的動作指令,另一方面,驅動程序將硬件讀寫的狀態、從硬件上獲得的數據傳送給驅動程序,實現應用程序與驅動程序間的交互函數包括以下API函數;相應的API函數能夠激發驅動程序的消息。
接口API函數          驅動程序的中IRP
CreateFile            IRP_MJ_CREATE
CloseHandle         IRP_MJ_CLOSE
ReadFile              IRP_MJ_READ
WriteFile              IRP_MJ_WRITE
DeviceIoControl    IRP_MJ_DEVICE_CONTROL
    在應用程序中,用戶可以調用上述函數操作驅動程序,其中CreateFile( )用於打開驅動程序,在使用完驅動程序之後,可以用CloseHandle()關閉驅動程序,ReadFile( )用於從驅動程序中讀取數據,WriteFile()用以往驅動程序中寫入數據,在函數中,最重要的是DeviceIoControl(),通過定義各種ITL_CODE來實現應用程序與驅動程序間的通訊函數,並可以傳遞各種參數和數據。

六、驅動程序的安裝
1.手動安裝方法
    生成的驅動程序爲sys後綴,一般放於Windows\System32\Drivers目錄下,如果進行手動安裝,可以將生成好的驅動程序拷貝到該目錄中,然後修改註冊表,對於註冊表的修改,可以進入註冊表修改程序進行修改,也可編寫註冊表程序進行修改,以下爲一註冊驅動程序的註冊表文件示例。
REGEDIT4
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Device]
"Type"=dword:00000001
"Start"=dword:00000001
"ErrorControl"=dword:00000001
"DisplayName"="Device"
"Group"="port"
"Tag"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Device\Parameters]
"IRQ Line"=dword:00000003
    直接在資源管理器下雙擊reg文件,在彈出的窗口上選擇“是”將直接修改註冊表,完成後,重新啓動Windows系統,將調用驅動程序。
2.編寫安裝文件INF
    INF文件含有安裝一個WDM設備驅動程序需要的所有必需的信息,包括賦值的文件列表,要創建的註冊表項等,Windows爲大多數類型的設備提供了一個標準的安裝程序。INF文件是一個文本文件,由節組成,每一節從括在方括號中的節的名稱開始,後面是節的內容,每一行可以是簡單的一項,或者設置一個一個值。具體的INF文件編寫可以參考現成的示例。
DDK安裝完成後,其中存在工具GenINF,可以按照該向導進行INF文件的編寫。
3.利用API函數編程實現驅動程序的安裝
    利用API函數實現註冊表的安裝,其實是利用訪問註冊表的API函數訪問修改註冊表,實現驅動程序的安裝。這種方法完全可以嵌入到我們的應用程序中,以下提供了安裝驅動程序的API代碼。主要的API函數包括RegCreateKeyEx(),RegSetValueEx(),RegQueryValueEx(),RegCloseKey() 。

七、驅動程序的調試
由於驅動程序的所有信息不能直接輸出到屏幕上,所以驅動程序的調試較一般應用程序要難得多,在調試時,可以利用應用程序中的DeviceIoControl()獲取驅動程序的狀態,也可藉助調試工具SoftIce,比較方便的工具是SysInternals公司的DebugView,如果驅動程序中帶有調試語句信息DbgPrint(),可以直接將該函數提供的信息顯示到屏幕上。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章