天天看點

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

    • 實體記憶體
      • 實驗一:了解MmNumberOfPhysicalPages
    • MmPfnDatabase
      • _MMPFN
        • 實體頁狀态
        • 六個連結清單
      • 實驗二:了解零化連結清單
      • 實驗三:檢視程序占用的所有實體頁

實體記憶體

最大實體記憶體

  1. 10-10-12分頁:最多識别4GB實體記憶體
  2. 2-9-9-12分頁:最多識别64GB實體記憶體

作業系統限制

  1. 在xp系統中,即使采用2-9-9-12分頁,仍然無法使用超過4GB的實體記憶體(可了解為 4GB以上的記憶體條)
  2. 而在windows 2003或windows 2008系統中,即使為32位系統,但若采用2-9-9-12分頁,就可以識别4GB以上的實體記憶體

思考:為什麼?

答案:由核心檔案中的幾個函數限制

實際實體記憶體

實體記憶體總數 = MmNumberOfPhysicalPages * 4

實驗一:了解MmNumberOfPhysicalPages

1)打開任務管理器,檢視實體記憶體

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

2)檢視MmNumberOfPhysicalPages(機關:實體頁)

指令:dd MmNumberOfPhysicalPages
Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

3)計算實體記憶體

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

結論:

實體記憶體總數 = MmNumberOfPhysicalPages * 4

思考:這麼多實體記憶體,作業系統如何進行管理

答案:通過全局數組

MmPfnDatabase

MmPfnDatabase

描述:

  1. 全局結構體數組,稱為“頁幀資料庫”,包含了目前作業系統中所有的實體頁
  2. 每一個實體頁都有一個對應的MMPFN結構體
  3. 通過全局變量MmPfnDatabase可以找到這個結構體的起始位置(在WinDbg中使用指令

    dd MmPfnDatabase

    進行檢視)
  4. 每一個MMPFN結構體之間在記憶體中是緊挨着的

定義:

_MMPFN *MmPfnDatabase

長度:

MmNumberOfPhysicalPages

_MMPFN

//FROM WinDbg
nt!_MMPFN
   +0x000 u1               : __unnamed
   +0x004 PteAddress       : Ptr32 _MMPTE
   +0x008 u2               : __unnamed
   +0x00c u3               : __unnamed
   +0x010 OriginalPte      : _MMPTE
   +0x018 u4               : __unnamed
           
//FROM WRK v1.2
typedef struct _MMPFN {
    union {
        PFN_NUMBER Flink;
        WSLE_NUMBER WsIndex;
        PKEVENT Event;
        NTSTATUS ReadStatus;

        //
        // Note: NextStackPfn is actually used as SLIST_ENTRY, however
        // because of its alignment characteristics, using that type would
        // unnecessarily add padding to this structure.
        //

        SINGLE_LIST_ENTRY NextStackPfn;
    } u1;
    PMMPTE PteAddress;
    union {
        PFN_NUMBER Blink;

        //
        // ShareCount transitions are protected by the PFN lock.
        //

        ULONG_PTR ShareCount;
    } u2;
    union {

        //
        // ReferenceCount transitions are generally done with InterlockedXxxPfn
        // sequences, and only the 0->1 and 1->0 transitions are protected
        // by the PFN lock.  Note that a *VERY* intricate synchronization
        // scheme is being used to maximize scalability.
        //

        struct {
            USHORT ReferenceCount;
            MMPFNENTRY e1;
        };
        struct {
            USHORT ReferenceCount;
            USHORT ShortFlags;
        } e2;
    } u3;
#if defined (_WIN64)
    ULONG UsedPageTableEntries;
#endif
    union {
        MMPTE OriginalPte;
        LONG AweReferenceCount;
    };
    union {
        ULONG_PTR EntireFrame;
        struct {
#if defined (_WIN64)
            ULONG_PTR PteFrame: 57;
#else
            ULONG_PTR PteFrame: 25;
#endif
            ULONG_PTR InPageError : 1;
            ULONG_PTR VerifierAllocation : 1;
            ULONG_PTR AweAllocation : 1;
            ULONG_PTR Priority : MI_PFN_PRIORITY_BITS;
            ULONG_PTR MustBeCached : 1;
        };
    } u4;

} MMPFN, *PMMPFN;
           

MMPFN與實體頁的對應關系:

  1. 通過目前MMPFN結構體找到對應的實體頁

    實體頁 = 目前_MMPFN索引值*0x1000

  2. 通過目前實體頁找到對應的MMPFN結構體

    _MMPFN = *MmPfnDatabase + 0x1c*(實體頁/0x1000)

實體頁狀态

MMFPN->u3.e1定義:

//FROM WRK v1.2
typedef struct _MMPFNENTRY {
    USHORT Modified : 1;
    USHORT ReadInProgress : 1;
    USHORT WriteInProgress : 1;
    USHORT PrototypePte: 1;
    USHORT PageColor : 4;
    USHORT PageLocation : 3;		//決定了目前頁的狀态,空閑情況下分為六種狀态
    								//0:MmZeroedPageListHead
    								//1:MmFreePageListHead
    								//2:MmStandbyPageListHead
    								//3:MmModifiedPageListHead
    								//4:MmModifiedNoWritePageListHead
    								//5:MmBadPageListHead
    USHORT RemovalRequested : 1;
    USHORT CacheAttribute : 2;
    USHORT Rom : 1;
    USHORT ParityError : 1;
} MMPFNENTRY;
           

六個連結清單

描述:windows通過六個連結清單,将所有相同類型的實體頁串到一起

  1. MmZeroedPageListHead

    零化連結清單(是系統在空閑的時候進行零化的,不是程式自己清零的那種)
  2. MmFreePageListHead

    空閑連結清單(實體頁是周轉使用的,剛被釋放的實體頁是沒有清0,系統空閑的時候有專門的線程從這個隊列摘取實體頁,加以清0後再挂入MmZeroedPageListHead)
    MMPFNLIST MmZeroedPageListHead = {
    	0, // Total
    	ZeroedPageList, // ListName
    	MM_EMPTY_LIST, //Flink
    	MM_EMPTY_LIST  // Blink
    };
               
    此時,MMPFN對應結構體如下:
    typedef struct _MMPFN {
        PFN_NUMBER Flink;
        PMMPTE PteAddress;
        PFN_NUMBER Blink;
        u3;
        MMPTE OriginalPte;
        u4;
    } MMPFN, *PMMPFN;
               
  3. MmStandbyPageListHead

    備用連結清單(當系統記憶體不夠的時候,作業系統會把實體記憶體中的資料交換到硬碟上,此時頁面不是直接挂到空閑連結清單上去,而是挂到備用連結清單上,雖然我釋放了,但裡邊的内容還是有意義的)
  4. MmModifiedPageListHead
  5. MmModifiedNoWritePageListHead
  6. MmBadPageListHead

    壞鍊

實驗二:了解零化連結清單

1)在WinDbg中檢視全局變量MmPfnDatabase的值

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

2)檢視全局變量MmZeroedPageListHead的值

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

3)定位第一個零化連結清單

公式:

MmZeroedPageList[0] = MmPfnDatabase + MmZeroedPageListHead[3]*0x1c

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

4)檢視後四項(紅色代表Flink,藍色代表Blink)

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

總結:零化連結清單結構如下圖所示

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

實驗三:檢視程序占用的所有實體頁

1)在WinDbg中定位目标程序

Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

2)檢視該程序的EPROCESS結構體,定位偏移為0x1f8的成員

指令:kd> dt _EPROCESS 866bf7e8
kd> dt _EPROCESS 866bf7e8 
ntdll!_EPROCESS
   ......
   +0x1f8 Vm               : _MMSUPPORT
   ......
           

3)檢視_MMSUPPORT結構體

指令:dt _MMSUPPORT 866bf7e8+0x1f8
ntdll!_MMSUPPORT
   +0x000 LastTrimTime     : _LARGE_INTEGER 0x01d6e998`ed894368
   +0x008 Flags            : _MMSUPPORT_FLAGS
   +0x00c PageFaultCount   : 0xb7
   +0x010 PeakWorkingSetSize : 0xbd
   +0x014 WorkingSetSize   : 0xbd
   +0x018 MinimumWorkingSetSize : 0x32
   +0x01c MaximumWorkingSetSize : 0x159
   +0x020 VmWorkingSetList : 0xc0883000 _MMWSL
   +0x024 WorkingSetExpansionLinks : _LIST_ENTRY [ 0x864b2a9c - 0x8649323c ]
   +0x02c Claim            : 0
   +0x030 NextEstimationSlot : 0
   +0x034 NextAgingSlot    : 0
   +0x038 EstimatedAvailable : 0
   +0x03c GrowthSinceLastEstimate : 0xb7
           

4)檢視VmWorkingSetList

指令:dt _MMWSL 0xc0883000
nt!_MMWSL
   +0x000 Quota            : 0
   +0x004 FirstFree        : 0x1e
   +0x008 FirstDynamic     : 0xa
   +0x00c LastEntry        : 0x217
   +0x010 NextSlot         : 7
   +0x014 Wsle             : 0xc0883cfc _MMWSLE			//實體頁起始位址
   +0x018 LastInitializedWsle : 0x4c0					//實體頁個數
   +0x01c NonDirectCount   : 0x33
   +0x020 HashTable        : 0xc0a84000 _MMWSLE_HASH
   +0x024 HashTableSize    : 0x200
   +0x028 NumberOfCommittedPageTables : 2
   +0x02c HashTableStart   : 0xc0a84000 Void
   +0x030 HighestPermittedHashAddress : 0xc0e00000 Void
   +0x034 NumberOfImageWaiters : 0
   +0x038 VadBitMapHint    : 0x16
   +0x03c UsedPageTableEntries : [1536] 0x34
   +0xc3c CommittedPageTables : [48] 1
           

5)檢視最後一個成員

指令:dd 0xc0883cfc L4c2
Windows記憶體管理學習筆記(二)—— 實體記憶體的管理

繼續閱讀