老程序員作新方向,老樹發新芽,做爲菜鳥的我,寫點心得,用以記錄並與同行交流
1對一些概念的理解:
KMDF與UMDF。二者的框架,及使用VS生成的初始代碼基本相同,只有所包含的頭文件不一樣,連接的系統庫不一樣,最終生成的文件分別爲.sys和.dll。由於框架徹底相同,相互移植應該比較容易。
UMDF驅動運行在用戶空間,調試相對容易,程序崩潰時也不至於對系統影響太大。因此只要能實現,應該首選使用UMDF框架。
雖然說UMDF框架運行在用戶空間,但也不是說全部WIN32應用程序可使用的API都能正常工做。本人遇到過調用WMI組件在UMDF驅動中編譯失敗的問題,比較有趣的是使用C++調用時編譯失敗,但使用C文件調用時就正常。
上手
不管何時,微軟提供的例子都是最好的學習材料,並且某些例子自己就已經可以工做的很是出色。本人曾經使用其中提供的鍵盤過濾驅動,只修改了安裝文件中的設備路徑,就能夠正常安裝,穩定工做。因此當要開發一個驅動時,最快捷的方法是找到最接近其功能的例子,拿它來修改。如下所記錄的內容都基於一個例子,或者使用WDK的模板建立的驅動框架。
INF文件及安裝
INF文件中最重要的是硬件編號,即[Standard.NT$ARCH$]所指定的內容。這裏設定的硬件編號與實際安裝時使用的硬件編號必定要相同。不然安裝會失敗。
若是是設備管理器能直接看到的設備,若是一個ACPI設備,在設備管理器中安裝就能夠。若是咱們開發的設備驅動沒有對應的硬件設備結點,就須要使用devcon來安裝,該程序會建立硬件設備結點,並安裝驅動。devcon能夠在WDK的安裝目錄中找到。使用方法:
devcon.exe inf文件名稱 硬件設備結點(即inf文件中設置的結點)
例如,若是設備驅動的INF文件中有以下片斷:
[Standard.NT$ARCH$]
%mydriver.DeviceDesc%=mydriver_Device, Root\MyDriver
則devcon的用法爲:devcon.exe install xxx.inf Root\MyDriver
在測試階段,由於咱們的驅動沒有得到微軟提供的簽名,須要在系統中開啓測試簽名才能正常安裝,某些驅動甚至須要將驅動文件中的測試簽名證書安裝到系統信任的證書目錄中。開啓測試簽名的方法:bcdedit /set testsigining on
WHCK測試
若是隻是單純的學習WDK驅動開發,能夠不作WHCK測試,但若是是作產品,WHCK是必需要作的,須要注意的幾點:
1)server必須是 server2008 R2, server2012, server2016等的英文版。其它更新的server版本是否可用不清楚,但英文版本是必須的。
2)安裝server時注意不要安裝標準版,它沒有桌面,只有命令行,使用不便,至於基於它可否運行WHCK server,還真沒有試過。
3)若是一時找不到英文版本也沒有關係,安裝完,將界面改爲英文資源。
並修改註冊表以將系統默認語言改成英文。
將HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language
下面InstallLanguage的值改成0409。若是還有問題,能夠把同級的跟Language相關的註冊表值都改成:0409
4)最好使用真實機器安裝server,來運行WHCK服務器端。由於WHCK運行時間很長,可能須要幾天。放在開發機上一不當心關掉,就麻煩了。我試過在vmware中運行server, WHCK客戶端連不上。在服務端看不到測試機。
5)WHCK測試環境bug不少,須要問題不要心急,要多試。不行就重啓測試機,服務通常不須要重啓,實在沒辦法重啓它也是一種方法。
6)能夠在開發機上安裝whck的studio,用來鏈接到服務器,執行測試用例,而不須要登陸到服務器,比較方便。
指定驅動的類型
在調用WdfDeviceCreate以前調用:WdfDeviceInitSetDeviceType來設置驅動自身的類型,如:
WdfDeviceInitSetDeviceType(DeviceInit, FILE_DEVICE_ACPI); 將其設置爲一個基於ACPI的驅動。
若是咱們不依賴於其它總線,就能夠不調用這個函數。若是設置的類型不對就不能正常安裝。若是是過濾驅動,在調用它以前還須要調用WdfFdoInitSetFilter來申明本身是過濾驅動。
驅動中使用事件
UMDF驅動中能夠直接使用CreateEvent等用戶空間的API,這裏再也不贅述。KMDF中須要使用KeInitializeEvent來初始化一個Event, KeWaitForSingleObject來等待。KePulseEvent來釋放等待中的事件。
驅動中使用延時
KMDF驅動中使用KeDelayExecutionThread來作延時,須要注意的是:其時間單位是100納秒。若是延時1毫秒須要使用的值爲:10000。並且有一個變態的設計:咱們傳入的值若是爲負數,即表示須要等待的時間,若是爲正數,則表示須要等待到的時間,即若是使用正數,就須要讀出當前時間,加上要等待的時間之後再傳給KeDelayExecutionThread。相信仍是使用負數比較方便。
驅動相互調用
兩個KMDF驅動調用比較方便,在A驅動中WdfDeviceCreate以前調用WdfDeviceInitAssignName函數來爲本身申明一個名字。如:
DECLARE_CONST_UNICODE_STRING(devName, L"\\Device\\MyTestDevice");
status = WdfDeviceInitAssignName(DeviceInit, &devName);
這樣在B驅動中就可使用IoGetDeviceObjectPointer來獲取驅動A的相關信息,進而調用IoCallDriver來發送Iocontrol進行數據交互。
中斷級別(IRQ LEVEL)
相比應用開發,KMDF驅動開發有一個比較麻煩的問題是中斷級別。一樣的函數在不一樣的地方調用效果不必定相同。當函數報錯,發生崩潰等問題時查看微軟的幫助文檔,瞭解中斷級別對該函數的影響,及當前代碼運行在什麼樣的中斷級別上。