系统换页内存池的管理算法
换页内存池有两个,一个是系统全局范围的,一个是会话空间中的。起始地址分别位MmPagedPoolStart和MiSessionPoolStart。换页内存池有一个数据结构来描述其页面分配状态,定义如下:
typedef struct _MM_PAGED_POOL_INFO {
PRTL_BITMAP PagedPoolAllocationMap;
PRTL_BITMAP EndOfPagedPoolBitmap;
PMMPTE FirstPteForPagedPool;
PMMPTE LastPteForPagedPool;
PMMPTE NextPdeForPagedPoolExpansion;
ULONG PagedPoolHint;
SIZE_T PagedPoolCommit;
SIZE_T AllocatedPagedPool;
} MM_PAGED_POOL_INFO, *PMM_PAGED_POOL_INFO;
PagedPoolAllocationMap :用于指明每一个页面的分配状态
EndOfPagedPoolBitmap : 指示每个页面是否为一次内存申请的最后一个页面
FirstPteForPagedPool、LastPteForPagedPool :指定了内存池的地址范围
NextPdeForPagedPoolExpansion : 定义了换页内存池的下次扩展位置
PagedPoolCommit : 记录了换页内存池中有多少个页面以及分到了内存
AllocatepagedPool :记录了换页内存池已分配了多少页面
PagedPoolHint :指示了在分配页面时的起始搜索位置
系统全局换页内存池有MmPagedPoolInfo 定义;会话换页内存池由MmSessionSpace的PagedPoolInfo定义。
MmInitSystem调用MiBuildPagedPool 建立系统的换页内存池,本质就时填充MmPagedPoolInfo的成员,完成系统换页内存池的初始化。
MmSizeOfPagedPoolInBytes和MmSizeOfPagedPoolInPages记录了系统换页内存池的大小,最大不超过MmNonPagedSystemStart-MmPagedPoolStart的范围。
MmPagedPoolStart和MmPagedPoolEnd 分别记录了换页池的起始地址和结束地址。
MiBuildPagedPool 分配好换页内存池地址范围的第一个页表,即起始地址的页目录项(PDE)所指的页表,MmPagedPoolInfo的NextPdeForPagedPoolExpansion 为接下来的页表地址,即换页内存池地址范围的第二个页表的虚拟地址。然后调用MiCreateBitMap创建一个位图,位图的大小等于页面的数量,位图本身的内存是从非换页内存池中分配的。
然后MiBuildPagedPool调用InitializePool 初始化执行体换页内存池,最后,MiBuildPagedPool 设置预警阈值MiLowPagedPoolThreshold和MiHighPagedPoolThreshold,以便通知系统换页内存池的使用情况。
MiAllocatePoolPages 分配换页内存池的页面,参数PoolType 指定哪个内存池申请页面。
MiFreePoolPages根据待回收页面的起始地址确定内存池的类型。