1. 程式人生 > >檔案系統Minifilter驅動(四)

檔案系統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一文中描述的技術和指導方針.