淺議Windows 2000/XP Pagefile組織管理(http://webcrazy.yeah.net)

來源:互聯網
上載者:User
 
            淺議Windows 2000/XP Pagefile組織管理
            WebCrazy(http://webcrazy.yeah.net)

    任何時候系統記憶體資源相對磁碟空間來說都是相形見拙的。因為虛擬記憶體機制,使我們可以有相對豐富的地址資源(通常32bit的虛擬位址,可以有4G的定址空間),而這些資源對實體記憶體來說一般情況是總是綽綽有餘的。所以在現代作業系統中,總是在相對緊張時使用一些策略,如FIFO、LRU等將實體記憶體的一些頁面置入相對便宜的磁碟空間資源中。一般的UNIX系統,獨立使用一個分區,即swap partition。而這方面Windows只是使用普通的檔案,通常命名為pagefile.sys,位於各分區的根目錄中。由於受到用於pagefile的PTE的限制(PTE中使用4bit來識別操作的pagefile),所以Windows最多可以支援16個pagefile.sys。

    從上描述,pagefile.sys本身就是一個比較特殊的檔案,根據系統的情況它的大小是可擴充的,通常我們可以使用“控制台”的“系統”小Applet來設定。由於其特殊性,Windows在啟動階段會對每個pagefile.sys建立相應的FILE_OBJECT,並且設定SharedRead欄位為False,而且在System進程,每個FILE_OBJECT都分別有一個控制代碼指向,這樣即只允許系統自身對其操作,避免使用者對其進行刪除等誤操作。

    為了對pagefile.sys進行管理,Windows中有一個長度為16的數組,用於對pagefile.sys的組織。每個成員分別對應一個pagefile。這個數組由系統變數MmPagingFile指向,每個成員都是一個指向MMPAGING_FILE的結構,這個結構有如下的格式:

    +0x000 Size             : Uint4B
    +0x004 MaximumSize      : Uint4B
    +0x008 MinimumSize      : Uint4B
    +0x00c FreeSpace        : Uint4B
    +0x010 CurrentUsage     : Uint4B
    +0x014 PeakUsage        : Uint4B
    +0x018 Hint             : Uint4B
    +0x01c HighestPage      : Uint4B
    +0x020 Entry            : [2] Ptr32 _MMMOD_WRITER_MDL_ENTRY
    +0x028 Bitmap           : Ptr32 _RTL_BITMAP
    +0x02c File             : Ptr32 _FILE_OBJECT
    +0x030 PageFileName     : _UNICODE_STRING
    +0x038 PageFileNumber   : Uint4B
    +0x03c Extended         : UChar
    +0x03d HintSetToZero    : UChar
    +0x03e BootPartition    : UChar
    +0x040 FileHandle       : Ptr32 Void

通過這個結構,我們可以很容易的得到相應pagefile的使用方式(MaximumSize、MinimumSize、FreeSpace、CurrentUsage、PeakUsage,請參閱windbg的!vm命令),其對應的FILE_OBJECT等。另外通過FILE_OBJECT的DeviceObject與Vpb欄位,我們就可知道這個pagefile所處的分區及分區使用的檔案系統等等資訊。我們來詳細介紹一下Bitmap成員。

    Bitmap是一個RTL_BITMAP的結構,其定義在ntddk.h中:

    typedef struct _RTL_BITMAP {
        ULONG SizeOfBitMap;                     // Number of bits in bit map
        PULONG Buffer;                          // Pointer to the bit map itself
    } RTL_BITMAP;

    與頁框資料庫(Pfn Database)與虛擬記憶體(x86平台PAGE_SIZE 4k)一樣,Windows也將pagefile分割成4K一塊塊的大小,稱為一頁,每頁由Bitmap對應的1 bit指定狀態。1為佔用,0為空白閑。通過使用RtlFindClearBits或是RtlFindClearBitsAndSet等函數對Bitmap進行操作,尋找這些檔案的未用頁面。雖然Bitmap指明佔用狀態時,Windows常以4k為單位,但為了提高效能,Windows在一次寫pagefile的單位通常為64k(MmModifiedWriteClusterSize個頁)。還有MMMOD_WRITER_MDL_ENTRY,等我下面提及相關內容時再加以說明。

    先用windbg來消化一下上面的討論:

    kd> dd MmPagingFile l 10  //從輸出結果可以看出我的機子上設了兩個pagefile。
    80547020  80d2af80 feec1548 00000000 00000000
    80547030  00000000 00000000 00000000 00000000
    80547040  00000000 00000000 00000000 00000000
    80547050  00000000 00000000 00000000 00000000
    kd> dd @$p l 40   //第一個pagefile的情況。
    80d2af80  00006400 0000c800 00006400 00000c38
    80d2af90  000057c7 000057c7 00000000 00000000
    80d2afa0  feea1cb8 feea1c18 fecbb000 feddc428
            .
            .
            .

    kd> dd feddc428 l 4  //從上面給出的MMPAGING_FILE,很容易得到file object(Offset 0x2c)。
    feddc428  00700005 80ecf2f0 80ecf268 fee66c10

    kd> !devobj 80ecf2f0   //aFILE_OBJECT的結構在ntddk.h中給出,其第三個dword就是DEVICE_OBJECT。
    Device object (80ecf2f0) is for:
     HarddiskVolume2 /Driver/Ftdisk DriverObject 80d97030
    Current Irp 00000000 RefCount 1316 Type 00000007 Flags 00001150
    Vpb 80ecf268 Dacl e13d1484 DevExt 80ecf3a8 DevObjExt 80ecf490 Dope 80ecf210 DevNode 80d95bd0 
    ExtensionFlags (0000000000)  
    AttachedDevice (Upper) 80d954b8 /Driver/VolSnap
    Device queue is not busy.

    另外FILE_OBJECT的第四個dword(fee66c10)就是VPB結構,你使用!vpb分析分析,限於篇幅,我就不在這兒列出了。

    通過上面windbg的分析,我們已經基本上對pagefile有了一定的瞭解了,下面轉入記憶體子系列與IO子系統(調用FSD)對pagefile的組織管理。

    通常情況下,對於進程可見的永遠是虛擬位址,存取某個虛擬位址,對於不存在的地址(對於X86,即其PTE的P位為0),通過觸發硬體中斷(X86為int e),由軟體來對這些PTE進行解析,譬如原型PTE(我在《探究Windows 2000/XP原型PTE》中詳細介紹),或是過渡PTE(Transition PTE,某些頁面由於進程工作集修整等原因,成為可被使用的頁面,但這些頁面的內容當前對這些進程仍有效,可隨時重新使用,所以Windows使用Transition這個術語區別於純粹的Free或Zeroed列表,我在《解析Winndows 2000/XP實體記憶體管理》中提及PFN列表)等,而對於Page File,實際上也有一個對應的pte指向相應pagefile.sys,完成解析工作(MiResolvePageFileFault),處理分頁錯誤(通過IoPageRead,下面會介紹)。

    所以在繼續討論之前我們來說明一下Pagefile PTE,它的格式如下:

    Valid            : Pos 0, 1 Bit
    PageFileLow      : Pos 1, 4 Bits
    Protection       : Pos 5, 5 Bits
    Prototype        : Pos 10, 1 Bit
    Transition       : Pos 11, 1 Bit
    PageFileHigh     : Pos 12, 20 Bits

    對於Prototype PTE與Transition PTE,總有1bit用於識別相應的PTE,如上的Prototype欄位,但對於PageFile PTE,卻沒有對應的識別bit,實際上MiDispatchFault(由KiTrap0E調用),是在解析完Prototype PTE(MiResolveProtoPteFault)、Transition PTE(MiResolveTransitionFault)、還有MiResolveDemandZeroFault後,才調用MiResolvePageFileFault的,當然在MiResolveProtoPteFault處理過程中也是最後調用MiResolvePageFileFault的。

    假設我們存取一個當前駐留在pagefile中的頁面,通過MiDispatchFault,控制權轉到MiResolvePageFileFault後,他會根據PTE的PageFileLow來索引MMPAGING_FILE數組,即判斷這一頁面位於哪個pagefile.sys中,因為PageFileLow為4個bit,所以Windows最多可以支援16個pagefile.sys。這樣記憶體子系統根據這個索引從MmPagingFile中描述的頁檔案結構取出這個pagefile的FILE_OBJECT(上面介紹過)。加上PageFileHigh所指定的pagefile.sys的位移值,MiResolvePageFileFault通過返回一個值為0xC0033333的特殊NTSTATUS通知MiDispatchFault調用IoPageRead得到此頁面。IoPageRead的原型如下(定義於ntifs.h中):

    NTKERNELAPI
    NTSTATUS
    IoPageRead(
        IN PFILE_OBJECT FileObject,
        IN PMDL MemoryDescriptorList,
        IN PLARGE_INTEGER StartingOffset,
        IN PKEVENT Event,
        OUT PIO_STATUS_BLOCK IoStatusBlock
    ); 

    當然在調用IoPageRead之前,記憶體管理器必須分配一個物理頁面,必要的時候還要調用MiRemoveAnyPage騰出空間,然後調用MiInitializeReadInProgressPfn,將這一頁框置成ReadInProgress狀態,然後將IoPageRead所需要的MDL參數MemoryDescriptorList指向這一頁面。MDL的虛擬位址欄位也就是IoPageRead讀入的頁面映射的虛擬位址,也即滿足我們先前假設的分頁錯誤。

    IoPageRead實際上通過Allocate一個IRP,用DIRECT_IO的方式(即我們提供的MDL),然後設定一個Complete Routine,用於取消頁面讀取之前的ReadInProgress狀態,再通過IoCallDriver調用IO子系統調用對應的File System Driver(通常由FILE_OBJECT的VPB參數確定),至於FSD是如何讀取pagefile.sys的,這兒不加以討論,ntifs提供的fastfat的原始碼是學習的方向。

    需要指出的是IoPageRead是一個同步操作,即只有等待頁面讀完畢以後才可以往下處理。這也是MiDispatchFault只能運行於DISPATCH_LEVEL IRQL之下的主要原因。IoPageRead通過裝置分配的IRP的IRP_SYNCHRONOUS_PAGING_IO的標誌來實現同步的。另外他也設定了IRP_PAGING_IO、IRP_NOCACHE標誌,用於與FSD之間的特殊通訊要求。

    由於工作集修整等的需要,通過MiModifiedPageWriter(MPW)線程實行將某些頁面置入pagefile中。MPW使用MMPAGING_FILE結構的_MMMOD_WRITER_MDL_ENTRY類型的Entry進行操作,_MMMOD_WRITER_MDL_ENTRY不僅僅由MiModifiedPageWriter使用,他還要讓MiMappedPageWriter使用(用於Mapped file),所以_MMMOD_WRITER_MDL_ENTRY結構不僅函有MDL成員,還包含Control Area等等。限於篇幅,我不將其結構列出。MPW通過IoAsynchronousPageRead將頁面按前面說的一次MmModifiedWriteClusterSize個頁面寫入pagefile中。對於IoAsynchronousPageRead其使用的IRP flag是IRP_PAGING_IO與IRP_NOCACHE,說明他是非同步作業的。這也可從他的名字看出,區別於Windows提供的另一個相關過程IoSynchronousPageWrite,他是同步的。

    講到這兒,對於page file的組織管理的一些基本的印象應該是有的。最後需要指出的一點是,對於IoPageRead不僅僅是對於pagefile的,其也可以針對mapped file,還有MiModifiedPageWriter,要不是避免死結也不會區分出MiMappedPageWriter,實際上Windows內部記憶體管理器對於pagefile與mappedfile的管理使用是基本相同的,而FSD的處理也只是一點點的區別而已。所以結合我以前介紹的如Control Area等概念,對mapped file等的理解也是可以參照本文的。還有同樣的一句話,錯誤地方希望得到你的指點。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.