聲明:高手請一笑而過.>_<
檔案系統過濾驅動開發(一)裡面已經講了檔案系統過濾驅動綁定裝置的大概思路,剩下的就是一些細節處理部分.
首先說說fast I/O派遣函數,我們知道,IRP是預設的I/O請求處理機制,IRP可以用於同步或者非同步I/O,也可以用於緩衝和非緩衝I/O,同時還可以用於分頁I/O.記憶體管理器通過發送合適的IRP到檔案系統以處理缺頁錯誤.快速I/O是是特別設計用於快取檔案的快速同步I/O.在快速I/O操作中,資料是在使用者緩衝區和系統緩衝直接交換,繞過檔案系統和儲存介質驅動堆棧(儲存介質驅動不使用快速I/O).當接收到一個快速I/O的讀或寫請求如果要讀或寫的檔案資料都在系統緩衝當中,那麼請求可以馬上被滿足.否則就會產生缺頁錯誤,導致一個或多個IRP產生.當這種情況發生時,快速I/O常式要麼返回FALSE,或者讓調用者等待直到缺頁錯誤被處理.如果快速I/O常式返回FALSE,則請求的操作失敗,調用者必須產生IRP.檔案系統和檔案系統過濾器是必須支援IRP的,但是並不一定要支援快速I/O處理.但是,檔案系統和檔案系統過濾器需要實現快速I/O常式,即是檔案系統和檔案系統過濾器本身不支援快速I/O,也必須要定義快速I/O常式並返回FALSE(就是按照快速I/O常式的原型聲明函數,然後函數裡直接返回FALSE).當I/O管理器收到同步檔案I/O請求(區別於分頁I/O),它首先調用快速I/O常式.如果快速I/O常式返回TRUE,則請求被快速I/O常式完成.如果I/O常式返回FALSE,I/O管理器產生並發送IRP.檔案系統過濾驅動不要求必須支援控制裝置物件的I/O操作.但是,過濾裝置對象綁定了檔案系統或者卷是要求傳遞所有沒有識別或者不想處理的IRP到驅動棧中的下一層驅動.同時,過濾裝置對象綁定卷裝置的必須實現FastIoDetachDevice.
具體上面這個可以參考WDK文檔fast I/O vs. IRPs,由於我們是檔案系統過濾驅動,所以我們必須聲明並實現fast I/O.fast I/O的初始化如下,需要注意的是FastIoDispatch的空間需要我們自己分配:
pFastIoDispatch = ExAllocatePoolWithTag(NonPagedPool,<br />sizeof(FAST_IO_DISPATCH),<br />LZSB_POOL_TAG<br />);<br />if (!pFastIoDispatch)<br />{<br />IoDeleteSymbolicLink(&SymlinkName);<br />IoDeleteDevice(gLZSBFilterControlDeviceObject);<br />return STATUS_INSUFFICIENT_RESOURCES;<br />}</p><p>RtlZeroMemory(pFastIoDispatch, sizeof(FAST_IO_DISPATCH));<br />pFastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);</p><p>pFastIoDispatch->FastIoCheckIfPossible= LzsbfFastIoCheckIfPossible;<br />pFastIoDispatch->FastIoRead= LzsbfFastIoRead;<br />pFastIoDispatch->FastIoWrite= LzsbfFastIoWrite;<br />pFastIoDispatch->FastIoQueryBasicInfo= LzsbfFastIoQueryBasicInfo;<br />pFastIoDispatch->FastIoQueryStandardInfo= LzsbfFastIoQueryStandardInfo;<br />pFastIoDispatch->FastIoLock= LzsbfFastIoLock;<br />pFastIoDispatch->FastIoUnlockSingle= LzsbfFastIoUnlockSingle;<br />pFastIoDispatch->FastIoUnlockAll= LzsbfFastIoUnlockAll;<br />pFastIoDispatch->FastIoUnlockAllByKey= LzsbfFastIoUnlockAllByKey;<br />pFastIoDispatch->FastIoDeviceControl= LzsbfFastIoDeviceControl;<br />pFastIoDispatch->FastIoDetachDevice= LzsbfFastIoDetachDevice;<br />pFastIoDispatch->FastIoQueryNetworkOpenInfo= LzsbfFastIoQueryNetworkOpenInfo;<br />pFastIoDispatch->MdlRead= LzsbfFastIoMdlRead;<br />pFastIoDispatch->MdlReadComplete= LzsbfFastIoMdlReadComplete;<br />pFastIoDispatch->PrepareMdlWrite= LzsbfFastIoPrepareMdlWrite;<br />pFastIoDispatch->MdlWriteComplete= LzsbfFastIoMdlWriteComplete;<br />pFastIoDispatch->FastIoReadCompressed= LzsbfFastIoReadCompressed;<br />pFastIoDispatch->FastIoWriteCompressed= LzsbfFastIoWriteCompressed;<br />pFastIoDispatch->MdlReadCompleteCompressed= LzsbfFastIoMdlReadCompleteCompressed;<br />pFastIoDispatch->MdlWriteCompleteCompressed= LzsbfFastIoMdlWriteCompleteCompressed;<br />pFastIoDispatch->FastIoQueryOpen= LzsbfFastIoQueryOpen;</p><p>pDriverObject->FastIoDispatch = pFastIoDispatch;
對於不實現fast I/O產生的效率損失,書上是說很低.在10%以下,具體折中的做法可以判斷被綁定裝置是否實現了fast I/O,如果過實現,我們就直接調用底層裝置的fast I/O處理函數.如果沒有則直接返回FALSE.判斷可以使用的宏和具體的代碼可以參考下面(判斷FastIoDeviceControl函數):
#define VALID_FAST_IO_DISPATCH_HANDLER(_pFastIoDispatch, _FieldName) /<br />(((_pFastIoDispatch) != NULL) && /<br />(((_pFastIoDispatch)->SizeOfFastIoDispatch) >= /<br />(FIELD_OFFSET(FAST_IO_DISPATCH, _FieldName) + sizeof(void *))) && /<br />((_pFastIoDispatch)->_FieldName != NULL))</p><p>if (VALID_FAST_IO_DISPATCH_HANDLER(pFastIoDispatch, FastIoDeviceControl))<br />{<br />return (pFastIoDispatch->FastIoDeviceControl)(<br />FileObject,<br />Wait,<br />InputBuffer,<br />InputBufferLength,<br />OutputBuffer,<br />OutputBufferLength,<br />IoControlCode,<br />IoStatus,<br />pNextDeviceObject<br />);<br />}
to be continue...