手记

页面置换算法

页面置换算法


  • 功能:当出现缺页异常,需调入新页面而内存已满时,置换算法选择被置换的物理页面

  • 目标:尽可能减少缺页中断(页面的换入换出)次数。具体来说,把未来不再使用的或短期内较少使用的页面换出,通常只能在局部性原理指导下依据过去的统计数据来进行预测。 

  • 页面锁定(frame locking):用于描述必须常驻内存的操作系统的关键部分,或时间关键的应用进程(time-critical)。实现的方法是在页表中添加锁定标志位(lock bit)

比较不同的页面置换算法: 设置一个实验环境,记录一个进程对页访问的轨迹。 
虚拟地址跟踪(3,0) (1,9) (4,1)…… 
偏移可忽略,只用页号生成页面轨迹3,1,4 …… 

模拟一个页面置换的行为并且记录产生缺页的数量,越少越好 

局部页面置换算法

置换页面的选择范围仅限于当前进程占用的物理页面

最优页面置换算法
  • 基本思路:当一个缺页中断发生时,对于保存在内存当中的每一个逻辑页面,计算在它的也一次访问之间,还需等待多长的时间,从中选择等待时间最长的那个,作为被置换的页面。

  • 这只是一整理想的情况,在实际的系统中是无法实现的,因为操作系统无法直到每一个页面要等待多长时间以后才会再次被访问。

  • 可用作其他算法的评价的依据(在一个模拟器上运行某个程序,并记录每一次的页面的访问情况,在第二遍运行时间可使用最优算法)

                   

d最远,被置换出,e被加入。

先进先出算法first-in first-out ,FIFO 


  • 基本思路:选择在内存中驻留时间最长的页面并淘汰之。具体来说:OS维护着一个链表,记录了所有内存当中的逻辑页面。从链表的排序顺序来看,链首页面的驻留时间最长,链尾页面的驻留时间最短。当发生一个页面中断时,把链首页面淘汰出局,把新的页面添加到链表的末尾。 

  • 性能较差,调出的页面可能是经常要访问的页面(驻留时间长,本身就说明可能常用),有belady现象(给的物理页帧越多反而缺页越频繁),FIFO算法很少单独使用。 

                  


最近最久未使用算法(least recently used, LRU 

  • 思路:当一个缺页中断发生时,选择最久未使用的那个页面,并淘汰之。

  • 它是对最优置换算法的近似,以过去推未来。根据程序的局部性原理,即在最近一小段时间(最近几条指令),如果某些页面被频繁访问,那么在将来的一小段时间内,它们还可能再一次被频繁访问。反之,如果在过去某些页面长时间未被访问,那么将来它们还可能会长时间地得不到访问。

  •                

LRU算法需要记录各个页面使用时间的先后顺序,开销比较大,两种可能的实现方法。 

  • 系统维护一个页面链表,最近刚使用的页面作为首结点,最久未使用的页面作为尾结点,每次访问内存时,找到相应的页面,把它从链表中摘下来,再移动到链表之首,每次缺页中断发生时,淘汰链表末尾的页面。

  • 设置一个活动页面堆栈:当访问某页时,将此页号入栈顶,并去除栈内的重复页。当需要淘汰一个页面时,总是选择栈底的页面,它就是最久未使用的。

                     


时钟页面置换算法
  •  Clock 页面置换算法——LRU的近似,对FIFO的改进 

  • 基本思路:需要用到页表项的访问位(access bit),当一个页面被装入内存时,把该位初始化为0,然后如果这个页被访问(读/写)时,硬件把它置为1. 

  • 把各个页面组织成环形链表(类似钟表面),把指针指向最老的页面(最先进来);

  • 当发生一个缺页中断,考察指针所指向的最老的页面,若它的访问为为0,则立即淘汰。若访问为1,则把该位置为0,然后指针往下移动一格。如此下去,直到找到被淘汰的页面,然后把指针移动到它的下一格。

                            

页号0和1的访问位被置0,页号为1的页表项被替换,访问位置1,指针指向下一个位置页号7

        

产生4次缺页中断,比LRU差一些,在实践的系统中和LRU接近。

二次机会法(或者enhanced clock)
  • 思路:减少修改页的缺页处理开销

  • 修改Clock算法,使它允许脏页总是在一次时钟头扫描中保留下来,同时使用脏位(dity bit,也叫写位)和使用位来指导置换

                  

      

产生三次缺页中断,与LRU接近,优先替换只读页,对于可写页减少被替换概率,对硬盘读写次数少。

最不常用算法(least frequently used,LFU)
  • 基本思路:当一个缺页中断发生时,选择访问次数最少的那个页面,并淘汰之

  • 实现方法:对每个页面设置一个访问计数器,每当一个页面被访问时,该页面的访问计数器加1,淘汰计数值最小的那个页面

  • LRU/LFU区别:LRU考察的是多久未访问,时间越短越值得留在内存,LFU是访问次数/频度,次数越多越好。 

反例:一个页面在进程开始时使用的很多,但以后就不使用了。此时LFU就不适用了。把时间也考虑进去,在一段时间内考察LFU。比如,定期把次数寄存器右移一位。 

Belady现象
  • Belady现象:在采用FIFO算法时,有时会出现的物理页面数增加,缺页率反而提高的异常现象。

  • Belady现象原因:FIFO算法的置换特征与进程访问内存的动态特征是矛盾的,与置换算法的目标是不一致的(即替换较少使用的页面),因此,被它置换出去的页面不一定是进程不会访问的。

LRU、FIFO与Clock的比较
  • LRU和FIFO本质都是先进先出的思路,但LRU是针对页面的最近访问时间来进行排序,所以需要在每一次页面访问的时候动态的调整各个页面之间的先后顺序(每一个页面的最近访问时间变了);而FIFO针对页面进入内存的时间来进行排序,这个时间是固定不变的,所以页面之间的先后顺序是固定不变的。如果程序局部性,则LRU会很好。如果内存中所有页面都没有被访问过会退化为FIFO(如页面进入内存后没有被访问,最近访问时间与进入内存的时间相同)。 

  • LRU算法性能较好,但系统开销较大;FIFO算法的系统的开销较小,但可能发生Belady现象。因此,择衷的办法就是Clock算法,在每一次页面访问时,它不必去动态调整页面在链表中的顺序,而仅仅是做一个标记,等待发生缺页中断的时候,再把它移动到链表的末尾。对于内存当中未被访问的页面,Clock算法的表现与LRU一样好,而对于那些曾经访问过的页面,它不能像LRU那样记住它们的准确访问顺序。

全局页面置换算法

全局页面置换算法置换页面的选择范围是所有可换出的物理页面

全局置换需要解决的问题:

  • 进程在不同阶段的内存需求是变化的

  • 分配给进程的内存也需要在不同阶段有所变化

  • 全局置换算法需要确定分配给进程的物理页面数

工作集模型

前面介绍的各种页面置换算法都是基于一个前提,即程序的局部性原理。

  • 如果局部性原理不成立,那各种算法都没啥区别,也就没什么意义。比如进程对逻辑页面的访问顺序是单调递增,那么在页面数有限的前提下,不管哪种算法都会缺页中断。 

  • 如果局部性原理成立,那么如何证明它的存在,如何对它进行定量分析,这就是工作集模型。

工作集:一个进程当前使用的逻辑页面集合 ,可以用一个二元函数W(t,Δ)表示。

  • t是当前执行时刻

  • Δ是工作集窗口 (working-set window),一个定长的页面访问的时间窗口

  • W(t,Δ)就是在当前时刻t之前的Δ时间内所有访问页面组成的集合,在随t不断更新

  • | W(t,Δ)|是工作集的大小即页面数目。 

                    

工作集的变化:进程开始后,随着访问新页面逐步建立较稳定的工作集,当内存访问的局部性区域的位置大致稳定时,工作集大小也大致稳定。局部性区域的位置改变时,工作集快速扩张和收缩过渡到下一个稳定值

           

常驻集:在当前时刻,进程实际驻留在内存当中的页面集合。

  • 工作集是进程在运行过程中固有性质,常驻集取决于系统分配给进程的物理页面数目和所采用的置换算法。

  • 如果一个进程的整个工作集在内存中,即常驻集包含工作集,那么进程会很顺利的运行,而不会造成太多的缺页中断(直到工作集发生剧烈变动,从而过度到另一阶段)

  • 当进程常驻集大小达到某个数目后,再分配更多的物理页面,缺页率也不会明显下降。可以把多出来的物理页面分给其他程序了。

工作集置换算法: 
  • 思路:换出不在工作集中的页面,

  • 当前时刻前τ个内存访问的页引用是工作集,τ被称为窗口大小

  • 实现方法:维护窗口内的访存页面链表,访存时,换出不在工作集的页面;更新访存链表。缺页时,换入页面;更新访存链表

                     

老的页会随着时间不断的换出,不管是否有缺页中断。确保物理页帧始终有空余的,给其他程序提供内存,在整个系统层面保证缺页率降低。

缺页率页面置换算法 

可变分配策略:常驻集大小可变 。例如:每个进程在刚开始运行的时候,根据程序的大小给它分配一定数目的物理页面,然后再程序的运行过程中,再动态的调整常驻集的大小

  • 可采用全局页面置换的方式,当发生一个缺页中断时,被置换的页面可以在其他进程中,各个并发进程竞争地使用物理页面。

  • 性能较好,但增加了系统开销 

  • 具体实现:可以使用缺页率置换算法(PFF, page fault frequency)动态调整常驻集的大小。


缺页率:缺页次数/ 内存访问次数或缺页平均时间间隔的倒数

影响缺页率的因素:

  • 页面置换算法

  • 分配给进程的物理页面数目(越多越小)

  • 页面本身的大小(页面大则会小)

  • 编程方法(局部性好就会小)

通过调节常驻集大小,使每个进程的缺页率保持在一个合理的范围内

  • 若进程缺页率过高,则增加常驻集以分配更多的物理页面

  • 若进程缺页率过低,则减少常驻集以减少它的物理页面数

                        

实现:

  • 访存时,设置引用位标志

  • 缺页时,计算从上次缺页时间tlast到现在tcurrent的时间间隔

  1. 如果tcurrent– tlast>T,则置换所有在[tlast, tcurrent]时间内没有被引用的页

  2. 如果tcurrent – tlast≤ T, 则增加缺失页到工作集中

                          

该算法与工作集置换算法不同点是,页的调整时间不一样,前者只是在中断时进行调整,后者在每一个时间都在调整。这两个算法都是工作集大小或缺页频率大小动态调整内存中需要的页的情况,局部算法只是在满的时候进行调整。这样确保经常访问的页驻留在内存中,应对多个程序时采用全局页置换算法好于局部页置换算法。

抖动问题
  • 如果分配给一个进程的物理页面太少,不能包含整个工作集,即常驻集属于工作集,进程会造成很多的缺页中断,频繁在内外存之间替换页面,使进程的运行慢,这种状态称为”抖动”。 

  • 产生抖动的原因:随着驻留内存的进程数目增加,分配给每个进程的物理页面数不断减少,缺页率上升。因此OS要选择一个适当的进程数目和进程需要的帧数,在并发水平和缺页率中达到平衡。 

抖动问题可能被本地的页面置换改善。更好的是加载控制,通过调节并发进程数(MPL)来进行系统负载控制

  • ∑WSt=内存的大小

  • 平均缺页间隔时间(MTBF)=缺页异常处理时间(PFST)

原文出处

2人推荐
随时随地看视频
慕课网APP