其意义是,根据最后一个工作集页面判断是否超出工作集的范围(Maximum)
PAGE_SIZE/sizeof(MMWSLE)是一个页面可以容纳MMWSLE的数目。
页面老化操作主要由MiProcessWorkingSets调用MiAgingWorkingSet()实现,本函数的主要功能除了根据参数DoAging决定是否进行页面老化外,对本进程工作集中的无效页面数目进行估计。
◆函数原型:
◆参数说明:
INPMMSUPPORTVmSupport//工作集指针
INLOGICALDoAging//判断是否要进行老化操作
INPWSLE_NUMBERWslesScanned//用于控制本次扫描的页面数目
INOUTPPFN_NUMBERTotalClaim,//用于不可用页面估计
INOUTPPFN_NUMBERTotalEstimatedAvailable
◆功能分析:
变量说明:
当DoAging=True时执行步骤---,否则不进行老化操作直接执行---
(1)每次Aging操作并不是对本进程所有页面进行老化,而是仅仅针对从NextAgingSlot开始的1/2^MiAgingShift(4)个页面进行老化,这样经过2^MI_AGE_AGING_SHIFT秒可以对所有页面进行老化一次,对于特殊情况老化页面数目会不同:
Ø计算出的老化页面数NumberToExamine大于老的页面峰值8192
这样NumberToExamine=8192
Ø对于巨型机老化的页面数加以控制:
NumberToExamine=64
(2)确定了老化的页面数目后,在确定老化的起始位置,首先从NextAgingSlot开始在判断其是否为有效页面,如不是用MI_NEXT_VALID_AGING_SLOT确定下一个老化页面作为起始页面。
(3)循环NumberToExamine次,对访问过的页面掉用MI_RESET_WSLE_AGE将访问位置零;对未访问过的页面调用MI_INC_WSLE_AGE使Age增一(但不能超过3);
(4)与老化类似每次估计也不是对所有的页面估计,这里仅仅对1/2^MiEstimationShift(5)进行估计,所不同的是选择估计页面时,不像老化操作顺序选择页面,这里每隔2^MiEstimationShift(不是定植)个页面选择一个具体参见MI_NEXT_VALID_ESTIMA-
TION_SLOT,这里为什么不是考察连续页面的原因是显然的,因为这里最后要根据概率来估计整个工作集中无效页面数目,在整个页面集中分散取页面,作为整个页面集的样本,从理论上说更准却;
(5)确定SampleSize也分几种不同情况:
SampleSize=VmSupport->WorkingSetSize-WorkingSetList->FirstDynamic;
NumberToExamine=SampleSize>>MiEstimationShift,这是首选页面数,但还要看下面的几种情况是否满足:
a、控制参数WslesScanned如果大于(1024*1024*1024)/PAGE_SIZE说明是在biggermachine中可能有大量进程,这里避免过多扫描(估计操作)后面在进行重新计算估计页面数目和MiEstimationShift
b、如果NumberToExamine>8192(峰值),则NumberToExamine=8192,在比较大的系统中资源比较充足,这里减小搜索的数目,重新计算MiEstimationShift;
c、NumberToExamine>=MI_MINIMUM_SAMPLE,确定搜索的数目不能小于最小值64
(6)从FirstDynamic如果Wsle[CurrentEntry]无效,则调用MI_NEXT_VALID_ESTIMATION-
_SLOT重新计算新的起始估计位置存于CurrentEntry中
(7)从CurrentEntry开始估计无效页面数目存于SampledAgeCounts数组中
(8)通过MI_CALCULATE_USAGE_ESTIMATE(SampledAgeCounts,CounterShift)根据概论理论估计本工作集中无效页面数目
(9)将估计的结果存储于本工作集中:
VmSupport->Claim=Claim;
VmSupport->EstimatedAvailable=Estimate
(10)用估计的结果,修改本函数参数TotalClaim和TotalEstimatedAvailable使之返回调用程序。
MiRemoveWsle()函数分析
◆函数原型:
◆参数说明:
INWSLE_NUMBEREntry:
要释放的工作集页面索引
INPMMWSLWorkingSetList:
进程工作集页面链表指针
◆功能分析:
(1)将工作集页面(Wsle[Entry])保存在临时变量WsleContents中
(2)判断当前进程工作集是否是系统工作集,进而判断属于系统工作集的那一类,对相应计数器减一
(3)设置工作集页面的有效位无效WsleContents.u1.e1.Valid=0;Wsle[Entry].u1.e1.Valid
(4)在哈希链表中删除此页,这里的情况是:
页面在Wsle中存储可能没有在哈希链表中存储(原因不明),所以接下来的查找可能失败,通过查找过程可以发现哈希链表的组织形式是线性的:
具体操作如下:
通过Hash=MI_WSLE_HASH(WsleContents.u1.Long,WorkingSetList);得到我们搜索的起始位置,
从Hash向后搜索,直至找到虚拟地址与由WsleContents得到的虚拟地址相同的哈希链表项。
如果找到尾,那么再从哈希链表头开始寻找,直至找到开始的位置Hash,这样保证整个哈希链表搜索过一遍
找到后将Table[Hash].Key置零。
从这里也可以看出hashtable的结构是线性结构,
四、实验分析
页面老化与修剪
从平衡集管理器入手,寻找老化原因,确定修剪、老化标准。
当空闲页面紧张,可以通过修剪工作集获得更多的空闲页面。
由每秒一次触发的KeBalanceSetManager启动工作集管理线程WorkingSetManager,在工作集管理线程中首先调用MiComputeSystemTrimCriteria函数确定当前需要进行的操作,主要包括工作集修剪、工作集老化以及空操作,这三种情况的触发条件如下
修剪时刻:
根据如下三个条件
当前可用页面数Available少于当前需要的页面数
本工作集中已经有被替换页面的记录,MiReplacing==TRUE
有超过可用页面数1/4的页面被循环用作后备页面
以上条件满足一个则立即进行修剪操作,其中设置Criteria标准的相应变量;
老化时刻:
当修剪条件全不成立时,当前可用页面Available小于限值20000,则进行老化操作;
不操作:
在1,2均不成立条件下,说明当前系统中还有大量内存可用,OutFlags=0,作为返回值,不进行任何操作。
至此已经确定了工作集处理的标准,保存在WorkingSetRequestFlags(OutFlags=0)和TrimCriteria中,如果WorkingSetRequestFlags非零,即需要进行修剪或者老化操作,具体调用MiProcessWorkingSets(WorkingSetRequestFlags,&TrimCriteria)做具体处理(下段介绍),如果WorkingSetRequestFlags为零,则不做操作,接下来查看修改页面链表的计数器MmModifiedPageListHead.Total是否超过限制MmModifiedPageMaximum,若超过则激活修改页面写回器工作。
以上整个过程函数调用链如下:
KeBalanceSetManager()
MmWorkingSetManager()
MiComputeSystemTrimCriteria()//工作集管理线程MI_AGE_ALL_WORKING_SETS
MiComputeSystemTrimCriteria()//工作集管理线程MI_AGE_ALL_WORKING_SETS
MiProcessWorkingSets()
MiTrimWorkingSet()////根据MI_TRIM_ALL_WORKING_SETS确定剪支
MiTrimWorkingSet()
MiAgeWorkingSet()//根据MI_AGE_ALL_WORKING_SETS判断是否老化
MiAgeWorkingSet()
MiProcessWorkingSets()
MmWorkingSetManager()
KeBalanceSetManager()
页面修剪操作主要由MiProcessWorkingSets调用MiTrimWorkingSet()具体实现。