檔案系統Minifilter驅動(四)
四、控制Filter管理器操作
在早於Vista的Windows中,filter管理器的操作由登錄檔中下列REG_DWORD AttachWhenLoaded值控制:
HKLM/System/CurrentControlSet/Services/FltMgr
當AttachWhenLoaded被設定為零時,filter管理器不會繫結到任何捲上直到某個minifilter驅動向filter管理器註冊.當AttachWhenLoaded被設定為1時,filter管理器在引導時繫結到所有捲上。
2K SP4及以後或XP SP2及更高版本上AttachWhenLoaded的預設值為零。2K3 SP1及後來版本上AttachWhenLoaded預設值為1.
Vista中AttachWhenLoaded值不存在.
當minifilter驅動安裝到Vista之前的Windows版本上,軟體安裝器應置AttachWhenLoaded為1.若修改前AttachWhenLoaded的值為零,則安裝器應在minifilter驅動安裝之後重啟系統.
五、開發和測試工具
本節描述的filter管理器工具在2K3 SP1的IFS Kit和Vista及以後版本的OS中提供了.
也鼓勵Minifilter驅動開發者使用多用途的核心模式開發和測試工具,比如帶驅動指定的規則的PREfast.
Fltmc.exe 控制程式
Fltmc.exe控制程式是common minifilter驅動管理操作的命令列應用. 開發者可以使用Fltmc.exe來載入和解除安裝minifilter驅動,繫結minifilter驅動到卷或從卷斷開,以及列舉minifilter驅動、例項和卷.
!fltkd Debugger Extension
!fltkd偵錯程式擴充套件命令在Debugging Tools for Windows中已經提供了.常用命令如下:
命令 |
描述 |
!cbd |
filter管理器等價於!irp |
!filter |
列出指定的filter的詳細資訊 |
!filters |
列出所有已繫結的minifilter驅動 |
!frames |
列出所有filter管理器frame和已繫結的minifilter驅動 |
!instance |
列出指定的例項的詳細資訊 |
!volume |
列出指定卷的詳細資訊 |
!volumes |
列出所有卷和已繫結的minifilter驅動例項的詳細資訊 |
更多額外的除錯幫助,要用除錯版本的Fltmgr.sys測試minifilter驅動,它包含眾多的 ASSERT來捕獲一般錯誤.
Filter Verifier
Filter Verifier是Driver Verifier 中的一個I/O Verification 選項,它驗證minifilter驅動對filter管理器函式的使用. 安裝Filter Verifier要用filter管理器.開發者應總是開發minifilter驅動時使用Driver Verifier和Filter Verifier.
要使用Filter Verifier,需指定minifilter驅動的名並激活Driver Verifier(Verifier.exe)中的I/O Verification選項.當minifilter驅動向filter管理器註冊時校驗就會啟動.
Filter Verifier在minifilter驅動中的有效用法如下:
糾正引數的使用和context的呼叫
糾正pre-oper和post-oper callback例程的返回值
使callback資料中引數的改變一致而連貫
Filter Verifie跟蹤以下filter管理器objects:
Contexts
Callback資料機構
Queued Work Items
NameInformation結構
File Objects
Filter Objects
例項Objects
卷Objects
六、嵌入Legacy過濾驅動的指導方針
微軟鼓勵開發者嵌入legacy過濾驅動到filter管理器模型中來獲得更好的效能提高系統穩定性. 有經驗的開發者會發現把legacy過濾驅動嵌入到minifilter驅動中相對容易。微軟的過濾驅動開發者被推薦用以下方法:
首先用一套可靠的衰退測試來驗證legacy過濾驅動和被嵌入的 minifilter驅動之間的行為.
建立一個minifilter驅動外殼並系統地從legacy過濾驅動中移植功能到minifilter驅動.例如,令attachment保持工作,然後每次嵌入一個操作,在操作之後進行測試。
最後改變使用者模式/核心模式通訊,以便你可以使用現有工具來測試minifilter驅動.
用PREfast編譯並激活Driver Verifier中的Filter Verifier I/O verification選項來測試.
在嵌入過程期間,你應該回顧所有的legacy過濾驅動程式碼來充分利用filter管理器的能力.尤其是要記住下面的:
如果合適基於IRP I/O和fast I/O的操作用相同的操作,這會減少程式碼的複製.
當註冊操作時,minifilter驅動可以明確選擇忽視所有的分頁I/O和cached I/O,出去檢查這些的程式碼.
例項通知大大簡化了attach/detach邏輯.
僅註冊minifilter驅動必須處理的操作;你可以忽視其他所有的事情.
利用filter管理器context和名管理支援.
利用filter管理器對發出非遞迴I/O的支援.
minifilter驅動不能以來區域性變數來維護從pre-oper處理到post-oper處理的context.可以分配一個lookaside列表來儲存操作狀態.
當一個名或context結束時確定釋放了引用.
使用者模式中的完成埠為構造佇列添加了一項強大的技術。你大概只需要一個單一的連線到一個單一的已命名的埠.
下表列出了legacy過濾驅動中的一般操作和它們是如何對映到filter管理器模型的.
Legacy 過濾驅動模型 |
Filter管理器模型 |
沒有完成例程的Pass-through操作 |
如果你的minifilter驅動從不為這種型別的I/O操作工作,則無需為其註冊pre-oper或post-oper callback例程. 否則,從為此操作註冊pre-oper callback例程中返回 FLT_PREOP_SUCCESS_NO_CALLBACK. 看Returning FLT_PREOP_SUCCESS_NO_CALLBACK一文. |
帶有完成例程的Pass-through操作 |
從pre-oper callback例程中返回 FLT_PREOP_SUCCESS_WITH_CALLBACK. 看Returning FLT_PREOP_SUCCESS_WITH_CALLBACK. |
在 pre-oper callback 例程中pend操作 |
需要時呼叫FltLockUserBuffer來確保一切user buffer都被鎖住,以便在一個worker執行緒中它們能被訪問. 通過呼叫像FltAllocateDeferredIoWorkItem和 FltQueueDeferredIoWorkItem這樣的支援例程queue工作到一個為worker執行緒. 從pre-oper callback例程中返回FLT_PREOP_PENDING. 當準備好返回I/O操作到filter管理器時,呼叫FltCompletePendedPre-oper. 看Pending an I/O Operation in a Pre-oper Callback Routine. |
在post-oper callback例程中pend操作 |
在pre-oper callback例程中,呼叫 FltLockUserBuffer來確保user buffers已經被鎖住,以便在一個worker執行緒中它們能被訪問. 通過呼叫像FltAllocateGenericWorkItem 和FltQueueGenericWorkItem這樣的支援例程來queue工作到一個worker執行緒. 從post-oper callback例程中返回 FLT_POSTOP_MORE_PROCESSING_REQUIRED. 當準備好返回I/O操作給filter管理器時,呼叫 FltCompletePendedPost-oper. 看 Pending an I/O Operation in a Post-oper Callback Routine. |
令操作同步 |
從pre-oper callback例程中返回 FLT_PREOP_SYNCHRONIZE. 看Returning FLT_PREOP_SYNCHRONIZE. |
在 pre-oper callback例程中完成操作 |
設定最終的操作狀態和資訊到該操作的FLT_CALLBACK_DATA 結構的成員IoStatus 中. 從pre-oper callback 例程中返回 FLT_PREOP_COMPLETE. 看Completing an I/O Operation in a Pre-oper Callback Routine. |
在操作已經於pre-oper callback例程中被pend之後完成該操作 |
設定最終的操作狀態和資訊到該操作的FLT_CALLBACK_DATA 結構的成員IoStatus 中. 從worker執行緒中呼叫FltCompletePendedPre-oper 來處理I/O操作,以CallbackStatus引數的形式傳遞FLT_PREOP_COMPLETE. 看Completing an I/O Operation in a Pre-oper Callback Routine. |
在完成例程中做所有的完成工作 |
從 post-oper callback例程中返回FLT_POSTOP_FINISHED_PROCESSING. 看Writing Post-oper Callback Routines. |
在安全的IRQL做完成工作 |
從 post-oper callback例程中呼叫FltDoCompletionProcessingWhenSafe. 看Ensuring that Completion Processing is Performed at Safe IRQL. |
從完成例程中Signal一個事件 |
從此操作的post-oper callback例程中返回FLT_PREOP_SYNCHRONIZE. filter管理器在IRQL <= APC_LEVEL像呼叫pre-oper callback例程一樣呼叫同一執行緒context中的post-oper callback例程. 看Returning FLT_PREOP_SYNCHRONIZE. |
令一個成功的create操作失敗 |
從create的post-oper callback例程中呼叫 FltCancelFileOpen. 設定一個適當的錯誤NTSTATUS值到該操作的 FLT_CALLBACK_DATA 結構的成員IoStatus 中. 返回FLT_POSTOP_FINISHED_PROCESSING. 看Failing an I/O Operation in a Post-oper Callback Routine. |
不接受某個I/O走fast I/O路線 |
從該操作的post-oper callback例程中返回FLT_STATUS_DISALLOW_FAST_IO. 看 Disallowing a Fast I/O Operation in a Pre-oper Callback Routine. |
修改某個I/O操作的引數 |
設定已修改的引數值到該操作的FLT_CALLBACK_DATA 結構的成員Iopb 中. 要通過呼叫FltSetCallbackDataDirty標記FLT_CALLBACK_DATA結構為dirty,除非你已經修改了FLT_CALLBACK_DATA結構的成員IoStatus中的內容. 看 Modifying the Parameters for an I/O Operation. |
鎖住這個操作的user buffer |
使用Accessing the User Buffers for an I/O Operation一文中描述的技術和指導方針. |