1. 程式人生 > >NT快取管理器(五)

NT快取管理器(五)

CcPurgeCacheSection

這個例程被FSD用來清除cache裡的所有頁面對映。被清除的資料從記憶體中被拋棄。如果資料在清掃之前被修改了,那麼對資料的更新就丟了。原型如下:

         NTKERNELAPI BOOLEAN CcPurgeCacheSection (

              IN PSECTION_OBJECT_POINTERS SectionObjectPointer,

              IN PLARGE_INTEGER FileOffset OPTIONAL,

              IN ULONG Length,

              IN BOOLEAN UninitializeCacheMaps

                );

SectionObjectPointer結構說明cache資料結構被用作這個操作的一部分。FileOffset是指向一個變數的指標,這個變數包含了檔案偏移資訊(這個偏移就是清除開始的地方)。Length表明要清掃的位元組數,從FileOffset開始計。UninitializeCacheMaps引數表明所有包含私有cache map資訊的檔案物件必須在清掃開始之前被反初始化。

如果SectionObjectPointer指定的section物件被使用來對映檔案到任何不是cache的地方,這個呼叫將會失敗。典型地,這種情況會發生當一個檔案被一個應用程式進行了記憶體對映,然後就不能被清掃只要這些對映一直存在。

FileOffset和Length引數一起告訴快取管理器什麼需要被清掃。

FileOffset        

Length            

Effect

NULL           

Any Value

Length is ignored and the whole file is purged

Any Value

NULL           

The file is purged from the byte indicated by FileOffset through the end of file

Any Value

Any Value

The file is purged beginning with the byte indicated by FileOffset for Length bytes.

FSD必須可以處理這個例程返回false的情況。在這種情況下,就不能去清掃cache中的資料了。

CcRepinBcb

這個例程被FSD用來增加相關計數在一個之前建立好的BCB上。原型:

          NTKERNELAPI VOID CcRepinBcb (

                IN PVOID Bcb

                );

FSD可能發現有必要使用之前生成 的BCB。這種情況下這個例程用來保證在這個操作期間Bcb仍然有效。

FSD負責釋放相關計數,呼叫CcUnpinRepinnedBcb。

CcSetAdditionalCacheAttributes

這個例程被FSD用來使能/使無效對一個檔案的預讀和後寫。原型如下:

          NTKERNELAPI VOID CcSetAdditionalCacheAttributes (

                IN PFILE_OBJECT FileObject,

               IN BOOLEAN DisableReadAhead,

               IN BOOLEAN DisableWriteBehind

               );

FileObject是指要建立額外屬性的檔案。快取管理器使用這個資訊來決定在檔案被訪期間cache的行為。如果DisableReadAhead是TRUE,那麼快取管理器將不會執行預讀操作。同樣地,如果DisableWriteBehind是TRUE,那麼快取管理器將會使快取的髒資料無效。取而代之的是,將會通過cache寫,但是寫將會持續一直到資料已經寫回磁碟了為止。

這會影響快取管理器呼叫CcCopyRead和CcCopyWrite。

CcSetBcbOwnerPointer

快取管理器使用這個資訊來決定誰是ERESOURCE(這東西內嵌在BCB中)的主人。儘管並不總是有用地,總有些奇怪現象就是ERESOURCE被一個執行緒獲得卻被另一個執行緒釋放。原型如下:

          NTKERNELAPI VOID CcSetBcbOwnerPointer (

               IN PVOID Bcb,

               IN PVOID OwnerPointer

               );

Bcb引數表明BCB包含了有問題的ERESOURCE。OwnerPointer是一個指向新主人/新執行緒的ETHREAD結構的指標。

CcSetDirtyPageThreshold

FSD可能會限制快取管理器為指定檔案維護的髒資料的數量。原型如下:

          NTKERNELAPI VOID CcSetDirtyPageThreshold (

               IN PFILE_OBJECT FileObject,

               IN ULONG DirtyPageThreshold

               );

一旦被快取的髒頁數目超過了DirtyPageThreshold,接下來的寫將會被阻止因為資料要從cache衝回磁碟。一旦髒頁數止掉到閾值以下,新的寫操作將會繼續了。

並沒有要求FSD設定這個限制。預設的是允許快取管理器和記憶體管理器來控制後寫策略。

CcSetDirtyPinnedData

這個呼叫被用來表明 由之前鎖定的BCB描述的快取塊裡的資料應該被標記為髒資料,不管這些資料有沒有被改變。原型如下:

          NTKERNELAPI VOID CcSetDirtyPinnedData (

               IN PVOID Bcb,

               IN PLARGE_INTEGER Lsn OPTIONAL

               );

Lsn引數應該被給成NULL,對於沒有使用WindowsNT日誌機制的檔案系統來說。

這個例程被FSD用來強制將資料寫回磁碟,儘管它都沒被改變

CcSetFileSizes

快取管理器依賴於FSD來告訴它什麼時候檔案大小被真正改變了。這個例程被FSD用來告訴快取管理器檔案大小變了。原型:

         NTKERNELAPI VOID CcSetFileSizes (

               IN PFILE_OBJECT FileObject,

               IN PCC_FILE_SIZES FileSizes

               );

FileObject指定哪個檔案的大小正被改變。FileSize是新的檔案大小。CC_FILE_SIZES資料結構關聯於 WindowsNT檔案系統用的普通頭結構的 檔案大小資訊。

當然FSD提供的sizes,兩個關鍵的大小是AllocationSize and FileSize。AllocationSize是可能被儲存在分配的空間上的資料的最大數量,被VM系統用來表明描述檔案的section大小。FileSize表明檔案裡現有的資料大小,被VM系統用來表明mapped view大小。

AllocationSize必須大於FileSize.

CcSetLogHandleForFile

為了完整性把這個例程列在了這裡。它被用在檔案系統(WindowsNT中採用內部日誌機制的檔案系統)裡。對於檔案系統來說不總是有用的。原型:

         NTKERNELAPI VOID CcSetLogHandleForFile (

               IN PFILE_OBJECT FileObject,

               IN PVOID LogHandle,

               IN PFLUSH_TO_LSN FlushToLsnRoutine

               );

CcSetReadAheadGranularity

這個例程被FSD用來控制快取管理器的預讀策略。原型:

         NTKERNELAPI VOID CcSetReadAheadGranularity (

               IN PFILE_OBJECT FileObject,

               IN ULONG Granularity

               );

WindowsNT 快取管理器預設的預讀尺寸是4K,儘管所有的都設成了64K.

粒度上必須是是2N*PAGE_SIZE.否則結果將會不可預測。

注意,記憶體管理器有一個64K的硬程式碼限制當從磁碟驅動器讀的時候。因而,即使你的FSD建立了大於64K的預讀尺寸,它也會通過一系列的64K預讀單元讀取。

CcUninitializeCacheMap

          NTKERNELAPI BOOLEAN CcUninitializeCacheMap (

               IN PFILE_OBJECT FileObject,

               IN PLARGE_INTEGER TruncateSize OPTIONAL,

               IN PCACHE_UNINITIALIZE_EVENT UninitializeCompleteEvent

          OPTIONAL

               );

通常在檔案物件被使用者應用程式關掉的時候要反初始化(Uninitializing)cache map。那會兒就必須執行一些操作來確定cache被正確地清掉。

對於一般的檔案來說,兩個可選引數被忽略了。程式碼看起來這樣地:

          CcUninitializeCacheMap(FileObject, 0, 0);

從字面上看,這是檔案提出的停止caching的請求。

如果這個函式返回TRUE,這是這個檔案的最後一個開啟例項,快取管理器清除共享的cache map(否則共享的cache map仍被該檔案的其它例項使用).

這個函式有一些有意思的副作用:

如果檔案被刪掉,TruncateSize引數將會指向一個LARGE_INTEGER(包含了檔案大小,典型的是0).這將會告訴快取管理器任何跟這個檔案相關的髒資料都不用寫回磁碟了-儘管也沒個保障,因為記憶體管理器可能決定寫回而不管檔案快取管理器怎樣怎樣。

如果檔案系統希望阻止以等到cache map被清除,它可以提供一個事件(這個事件能被用來等待共享cache map的最後崩潰)。

這個例程對於所有檔案物件都能被安全呼叫,儘管對於那些沒有呼叫CcInitializeCacheMap的檔案系統。

CcUnpinData

這個例程用來釋放鎖住的BCB塊。原型:

          NTKERNELAPI VOID CcUnpinData (

               IN PVOID Bcb

               );

FSD每一個對於CcPinRead,CcPreparePinWrite, and CcPinMappedData 的呼叫,這個例程釋放被鎖的BCB塊。當Bcb上的引用計數掉為0的時候,它能被快取管理器釋放掉,然後快取管理器的這段地址空間就能被重用了。

CcUnpinDataForThread

這個例程用來允許一個執行緒,除了最初請求BCB的那個,來釋放BCB裡的ERESOURCE。原型:

         NTKERNELAPI VOID CcUnpinDataForThread (

               IN PVOID Bcb,

               IN ERESOURCE_THREAD ResourceThreadId

               );

CcUnpinRepinnedBcb

這個例程被FSD用來釋放被呼叫了CcRepinBcb而鎖住的BCB塊。

         NTKERNELAPI VOID CcUnpinRepinnedBcb (

               IN PVOID Bcb,

               IN BOOLEAN WriteThrough,

               OUT PIO_STATUS_BLOCK IoStatus

               );

WriteThrough選項表明FSD是否願意確保髒資料被寫回磁碟在結束這個呼叫之前。如果WriteThrough是TRUE,那麼在結束這個例程的時候,IoStatus將會被設定來表明任何寫操作的結果。如果WriteThrough是FALSE,髒資料將會遲些被快取管理器的Lazy Writer寫回。

CcZeroData

這個例程被FSD用來保證記憶體中的一串被設為0.原型如下:

         NTKERNELAPI BOOLEAN CcZeroData (

               IN PFILE_OBJECT FileObject,

               IN PLARGE_INTEGER StartOffset,

               IN PLARGE_INTEGER EndOffset,

               IN BOOLEAN Wait

               );

典型地,FSD使用這個例程來清0新的資料區域,從而任何之前記憶體使用留下來的碎片被抹殺,對其它應用程式也不可用。

FileObject表明哪個檔案要被清0,StartOffset和EndOffset表明檔案裡要被清0的範圍。Wait引數表明呼叫者是否願意等待當任何必須的同步物件被獲得。

一般來講,這個呼叫不會引起磁碟I/O.如果偏移不在頁範圍內,一個預設頁會被啟用來獲得頁,從而沒被改變的頁將會被正確的儲存。更多地,如果FileObject表明檔案正在被寫語義開啟,那麼當頁被清0的時候它們會被寫回磁碟。

CcZeroEndOfLastPage

這個例程用來給這部分清0:檔案的最後一頁,最後一個有效位元組到物理頁的結束。原型如下:

         NTKERNELAPI VOID CcZeroEndOfLastPage(

               IN PFILE_OBJECT FileObject

               );

這個確保瞭如果文件被擴充套件,前面記憶體使用的資料變地不可訪問。這個呼叫不常被FSD呼叫,只是為了完整性包進來而已。

FsRtlMdlReadCompleteDev

這個例程對檔案系統過濾驅動很有用,因為它並不展示CcMdlReadComplete的重入行為,這可能在檔案系統過濾驅動從它自己的MdlReadComplete快速I/O入口點返回FALSE的時候導致資料丟失。

         NTKERNELAPI BOOLEAN FsRtlMdlReadCompleteDev(

PFILE_OBJECT FileObject,

               PMDL MdlChain,

               PDEVICE_OBJECT DeviceObject

               );

這被證明是快取管理器CcMdlReadComplete2的包裝,與NT3.51裡的CcMdlRadComplete有相同的語義。

注意這個呼叫在NT4.0 IFS kit裡是沒有地。

FsRtlMdlWriteCompleteDev

這個例程對檔案系統過濾驅動很有用,因為它並不展示CcMdlWriteComplete的重入行為,這可能在檔案系統過濾驅動從它自己的MdlReadComplete快速I/O入口點返回FALSE的時候導致資料丟失。

         NTKERNELAPI BOOLEAN FsRtlMdlWriteCompleteDev(

PFILE_OBJECT FileObject,

               PLARGE_INTEGER FileOffset,

               PMDL MdlChain,

               PDEVICE_OBJECT DeviceObject

               );

這被證明是快取管理器CcMdlReadComplete2的包裝,與NT3.51裡的CcMdlRadComplete有相同的語義。

注意這個呼叫在NT4.0 IFS kit裡是沒有地。