Windows内核情景分析-内存管理2

内核对于物理页面的管理

物理内存的管理和使用是以页面为单位的,所以物理内存的管理实际上是对物理页面的管理。 在系统初始化过程中,内核构建一个PHYSICAL_PAGE结构的数组,并使全局变量MmPageArray指向这个数组,系统存在多少物理页面,该数组就有多大。页面号(Pfn)为下标,物理地址与Pfn有着固定的对应关系,物理地址右移12bit得到的值,即为对应的物理页面。结构如下:

Windows内核情景分析-内存管理2

 Type字段表示物理页面的性质,有以下几种:空闲的页面、使用中的页面,以及用于BIOS的页面,如下图:

Windows内核情景分析-内存管理2

ListEntry结构用来将该结构加入 某队列,内核中有以下物理页面队列:

Windows内核情景分析-内存管理2

最低1MB范围中的页面都是用于BIOS的,所以都在BiosPageListHead队列之中。空闲队列FreeZeroedPageListHead是经过清零的页面队列。FreeUnZeroedPageListHead是未经清零的页面队列。 内核线程MmZeroPageThreadMain()受调度运行就从这个队列摘取物理页面,经过清零后加入FreeZeroedPageListHead队列。UsedPageListHeads[MC_MAXIMUM]是一个数组,里面有四个队列,表示在使用的物理页面队列;有四种:

Windows内核情景分析-内存管理2

分别为用于磁盘内容缓存的队列,用户空间物理内存队列,内核可倒换内存池队列,内核不可倒换内存池队列。

典型的物理页面周转过程:从FreeZeroedPageListHead队列开始,经分配使用某个用户空间虚存页面映射,进入UsedPageListHeads[MC_USER]队列,使用完毕后释放(或者虚存页面被倒换外存而释放),进入FreeUnzeroedPageListHead队列,内核线程MmZeroPageThreadMain()受调度运行进行清零,回到FreeZeroedPageListHead队列。

PFN_TYPE 定义:typedef ULONG PFN_TYPE, *PPFN_TYPE;

已分配使用的物理页面因用途的不同而各有各的队列,一方面便于归类管理,其次可以对各种类型页面的配额占用比例等进行管理。所以与UsedPageListHead[]数组平行,内核数组MiMemoryConsumers[],用于配额管理:

Windows内核情景分析-内存管理2

 PagesUsed记录已分配用于此种用途的物理页面数量,PagesTarget就是具体配额,函数指针Trim指向具体的修剪函数。当一种类型页面占用过多,空闲页面配额不足,就有可能触发修剪函数,将部分物理页面让出,转而使用外存替代。

PFN_TYPE  NTAPI  MmAllocPage(ULONG Consumer,SWAPENTRY savedSwapEntry)

该函数是用来实际从FreeZeroedPageListHead或FreeUnzeroedPageListHead物理页面队列中分配页面。

NTSTATUS NTAPI MmRequestPageMemoryConsumer(ULONG Consumer,BOOLEAN CanWait,PPFN_TYPE AllocatedPage) 

 该函数为特定Consumer请求分配一个物理页面。对于MC_NPPOOL或者页面平衡线程则直接调用MmAllocPage尝试分配,其他则要检查配额,如果配额用完,则需要调用修剪函数让出页面,然后分配;其次在总可用页面量小于特定值时,也会**页面平衡线程,等待释放物理页面后再操作,具体细节见书籍,应该都可以理解。