随机算法 先来先出(FIFO)算法 第二次机会算法 时钟算法
最优算法 NRU算法 LRU算法 工作集算法 工作集时钟算法
需要替换页面的时候,产生一个随机页面号,替换与该页面对应的物理页面。
更换最早进入内存的页面。
FIFO的实现机制是使用链表将所有在内存的页面按照进入时间的早晚链接起来,然后每次置换链表头上的页面就行了。
就是在使用FIFO更换一个页面时,需要看一下该页面是否在最近被访问过。
如果没有被访问过,则替换该页面。
如果该页面在最近被访问过(通过检查其访问位的取值),则不替换该页面,而是将该页面挂到链表末端,并将该页面进入内存的时间设置为当前时间,并将其访问位清零。
相当于给内存页面第二次机会。
在时钟算法里,我们把页面排成一个时钟的形状。
该时钟有一个针臂。每次需要更换页面时,我们从针臂所指的页面开始检查。如果当前页面的访问位为0,即从上次检查到这次,该页面没有被访问过,将该页面替换。如果当前页面被访问过,那就将其访问位清零,并顺时针移动指针到下一个页面。我们重复这些步骤直到找到一个访问位为0的页面。
时钟算法和第二次机会算法有点相似,但又不一样:
1.数据结构不一样,第二次机会使用的是链表,而时钟算法使用的是索引(整数指针)。
2.第二次机会算法需要使用额外的内存,而时钟算法可以直接使用页表。并且页表的访问位会定期自动清零,这样使得时钟算法的时间分辨粒度较第二次机会算法高。
在非公平的算法里面,最理想的页面替换算法是选择一个再也不会被访问的页面进行替换;如果不存在这样的页面,那至少选择一个在随后最长时间内不会被访问的页面进行替换——这就是最优更换算法。
其实,最优更换算法就是一种不会实际实现的算法。
存在的意义是为了定义一个标杆,以此来评判其他算法的优劣。
最近未使用算法(Not Recently Used,NRU),就是选择一个最近没有被访问的页面来替换,在所有的最近没有使用的页面里,按照各个页面的修改位和访问位的组合来进行划分。
页面类型 | 访问位状态 | 修改位状态 |
---|---|---|
1 | 没有被访问过 | 没有被修改过 |
2 | 没有被访问过 | 修改过 |
3 | 被访问过 | 没有被修改过 |
4 | 被访问过 | 修改过 |
注:2情况是可能的,系统对访问位会定期清零,对修改位却不能清零。
NRU算法就是按照这4类页面的顺序寻找可以替换的页面。
它首先看看内存页面里有没有第1种页面,有的话就将找到的第1个这种页面作为替换对象。
如果没有,则在第2种页面里面寻找;
若还没有,则在第3种页面里面寻找;
以此类推,如果所有页面皆被访问和修改过,那也只能从中替换掉一个页面。
因此,NRU算法总是会终结。
对NRU算法的改进就是LRU算法。LRU算法是最近使用最少算法(LeastRecently Used)。
该算法有多种实现方式:
最简单的办法就是在页表的记录项里增加一个计数域,一个页面被访问一次,这个计数器的值就增加1。这样,当需要更换页面时,只需找到计数域取值最小的页面替换即可,该页面即是最近最少使用的页面。
缺点:
LRU算法的另一种简单实现方式是用一个链表将所有页面链接起来,最近被使用的页面在链表头,最近未被使用的放在链表尾。在每次页面访问时对这个链表进行更新,使其保持最近被使用的页面在链表头。
缺点:
矩阵法,就是使用一个矩阵来记录页面的使用频率和时间。该矩阵为n×n维,n是相关程序当前驻内存的页面数。在一开始矩阵每行每列的初值为0。
每次一个页面被访问时,例如第k个虚拟页面被访问时,我们进行如下操作:
在每次需要更换一个页面时,选择矩阵里对应行值最小的页面更换即可。此处的行值是指把该行所有的0和1连起来看做一个二进制数时的取值。
例如,假定某个程序有4个虚拟页面,分别是0、1、2、3。该程序虚拟页面的访问顺序是:0,1,2,3,2,1,0,3,2,3。随着页面访问的进行,矩阵的状态变化如图:
在第1步操作后,我们已经保证该页面对应的行值为最大之一。而第2个操作将该页面对应的列置为0,则保证了该页面对应的行值为唯一的最大。
由于每个页面访问都会将某一列置为0,这样,越长时间没有被访问的页面,其对应的行元素里面被置为0的列个数就越多,即它对应的行值将越小,也就保证了其正确性。
优点:
缺点:
我们给每个存放在内存的页面配备一个移位寄存器。该寄存器用来记录该页面被访问频率和最近的属性。所有移位寄存器的初值皆为0。
然后在每个规定长度的周期内,将移位寄存器的值往右移动一位,并将对应页面的访问位的值加到该移位寄存器的最左位。
这样,当需要寻找一个页面进行更换时,只需要找到对应移位寄存器值最小的页面即可。该页面即是最近最少使用的页面。
例如,假定某程序有6个页面在内存中,页号分别为0、1、2、3、4、5。其对应的6个移位寄存器初值皆设置为0,如a)所示。
在第一个规定周期内,页面0、2、4、5的访问位为1,页面1和3的访问位为0。我们将移位寄存器往右移动一位,并将各个页面的访问位加到相应移位寄存器的左面,就得到图b)的状态。
在第2个规定周期内,页面0、1、4的访问位为1,而2、3、5的访问位为0,我们重复同样的操作获得图c)的状态。
假如第3个规定周期内页面0、1、3、5的访问位为1,2、4的访问位为0,则获得图d)的状态。
第4个周期内页面0、4被访问过,其他页面的访问位为0,得到图e)的状态,第5个周期内页面1、2被访问过,其他页面的访问位为0,得到图f)的状态。
这时如果需要替换页面,第3个页面所对应的移位寄存器里面的值最小,因此页面3将被替换。
优点:
缺点:
由于不可能精确地确定哪个页面是最近最少使用的,那就干脆不用花费这个力气,只维持少量的信息使得我们选出的替换页面不太可能是马上又会使用的页面即可。这种少量的信息就是工作集信息。
工作集概念来源于程序访问的时空局域性。即在一段时间内,程序访问的页面将局限在一组页面集合上。例如,最近k次访问均发生在某m个页面上,那么m就是参数为k时的工作集。我们用w(k,t)来表示在时间t时k次访问所涉及的页面数量。显然,随着k的增长,w(k,t)的值也随着增长;但在k增长到某个数值后,w(k,t)的值将增长极其缓慢甚至接近停滞,并维持一段时间的稳定。
由此可以看出,如果一个程序在内存里面的页面数与其工作集大小相等或超过工作集,则该程序可在一段时间内不会发生缺页中断。如果其在内存的页面数小于工作集,则发生缺页中断的频率将增加,甚至发生内存抖动。
工作集算法的实现如下:
为页表的每个记录增加一项信息用来记录该页面最后一次被访问的时间。这个时间不必是真实时间,只要是按规律递增的一个虚拟时间即可。同时我们设置一个时间值T,如果一个页面的最后一次访问在当前时间减去T之前,则视为在工作集外,否则视为在工作集内。
这样,在每次需要替换页面时,扫描所有的页面记录,并进行如下操作:
缺点:
工作集时钟算法,即使用工作集算法的原理,但是将页面的扫描顺序按照时钟的形式组织起来。
这样每次需要替换页面时,从指针指向的页面开始扫描,从而达到更加公平的状态。而且,按时钟组织的页面只是在内存里的页面,在内存外的页面不放在时钟圈里,从而提高实现效率。
鉴于其时间和空间上的优势,工作集时钟算法被大多数商业操作系统所采纳。