1.OPT最佳页面置换算法
选择的被淘汰页面,将是以后永久不会使用的 或者在未来最长时间内不会被访问的页面
但是人们目前无法预知未来。因而在算法上难以实现。
为某进程分配三个物理块,页面号引用串:
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
首先装入:
7 |
0 |
1 |
访问页面2时,产生缺页中断。
此时向后看
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
物理块中的7,0,1都在未来将被访问,但是 7是未来最长时间内不会被访问的页面。
因此置换7
2 |
0 |
1 |
2.FIFO先进先出页面置换算法
选择在页面驻留时间最久的页面予以淘汰。
驻留时间最久的怎么找?
我们用队列buffer来模拟物理块
7 |
0 |
1 |
当访问2时,产生缺页中断。
利用remove()去掉队首7,把2添加至队尾。
0 |
1 |
2 |
可以发现, 页面驻留时间最久的页面在队首,替换进来的新页面添加至队尾。所以驻留时间最久的页面总是在队首。
代码实现:
import java.util.LinkedList;
import java.util.Queue;
public class FIFO {
Queue<Integer> buffer = new LinkedList<Integer>();
int arry[]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};
int block=3;//物理块大小
int ChangeNum=0;
void fifo(){
System.out.println("--------------------FIFO算法---------------------");
System.out.println("访问序列 ");
for(int i=0;i<arry.length;i++)
{
System.out.print(arry[i]+" ");
}
System.out.println();
for(int i=0;i<=2;i++)
{
buffer.add(arry[i]);
}
show();
for(int i=block;i<arry.length;i++)
{
if(juge(arry[i]))
{
System.out.println(arry[i]+"在队列中,无需置换");
System.out.println();
}
else
{
//去掉驻留最久的--->队首 buffer.remove()
System.out.println(arry[i]+"不在队列,移除"+buffer.remove());
buffer.add(arry[i]);
ChangeNum++;
show();
}
}
}
//判断要访问的页面在不在物理块中
boolean juge(int k){
Object[] o =buffer.toArray();
for(int i=0;i<o.length;i++)
{
if((int)o[i]==k)
{
return true;
}
}
return false;
}
//显示现有物理块
void show(){
System.out.println("现有队列:");
Object[] o =buffer.toArray();
for(int i=0;i<o.length;i++)
{
System.out.println(o[i]);
}
System.out.println();
}
public static void main(String[] args) throws Exception {
FIFO f = new FIFO();
f.fifo();
System.out.println("----------页面置换次数"+f.ChangeNum+"------------");
}
}
结果:
--------------------FIFO算法---------------------
访问序列
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
现有队列:
7
0
1
2不在队列,移除7
现有队列:
0
1
2
0在队列中,无需置换
3不在队列,移除0
现有队列:
1
2
3
0不在队列,移除1
现有队列:
2
3
0
4不在队列,移除2
现有队列:
3
0
4
2不在队列,移除3
现有队列:
0
4
2
3不在队列,移除0
现有队列:
4
2
3
0不在队列,移除4
现有队列:
2
3
0
3在队列中,无需置换
2在队列中,无需置换
1不在队列,移除2
现有队列:
3
0
1
2不在队列,移除3
现有队列:
0
1
2
0在队列中,无需置换
1在队列中,无需置换
7不在队列,移除0
现有队列:
1
2
7
0不在队列,移除1
现有队列:
2
7
0
1不在队列,移除2
现有队列:
7
0
1
----------页面置换次数12------------
3.LRU最近最久未使用算法。
选择最近最久未使用的页面给予淘汰。
最近最久未使用的页面怎么找?
OPT是看未来(向后看),那么LRU就是回忆过去(向前看),即向前寻找当前物理块中的页面,直至全部找到,最后找到的一个,就是最近最久未使用的页面。
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
首先装入:
7 |
0 |
1 |
访问页面2:
产生缺页中断。此时向前看 ,7 0 1 2,物理块中的7,0,1全部找到,7是最后找到的,所以7是最近最近未使用的页面。
因此置换7
2 |
0 |
1 |
访问页面0:
0在页面中。不会产生缺页中断,因此不用置换。
访问页面3:
产生缺页中断,向前看。7 0 1 2 0 3,物理块中的2,0,1全部找到,1是最后找到的,所以1是最近最近未使用的页面。
因此置换1
2 |
0 |
3 |
访问页面0:
0在页面中。不会产生缺页中断,因此不用置换。
访问页面4:
产生缺页中断,向前看。7 0 1 2 0 3 0 4,物理块中的2,0,3全部找到,2是最后找到的,所以2是最近最近未使用的页面。
因此置换2
4 |
0 |
3 |
。。。。如此往复
代码实现:
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
public class LRU {
int arry[]={7,0,1,2,0,3,0,4,2,3,0,3,2,1,2,0,1,7,0,1};
int block=3;//物理块大小
int positon=0;//定位请求访问页面的位置
int ChangeNum=0;
LinkedList<Integer> stack = new LinkedList<Integer>();
void lru(){
System.out.println("--------------------LRU算法---------------------");
System.out.println("访问序列 ");
for(int i=0;i<arry.length;i++)
{
System.out.print(arry[i]+" ");
}
System.out.println();
//装载初始三个页面 7 0 1
for(int i=0;i<=2;i++)
{
stack.add(arry[i]);
positon++;
}
show();
for(int i=positon;i<arry.length;i++)
{
if(juge(arry[i]))
{
positon++;
System.out.println(arry[i]+"在页面中,无需置换");
System.out.println();
}
else
{
int m=change();
System.out.println(arry[i]+"不在页面中,移除"+arry[m]);
stack.remove((Integer)arry[m]);//如果只写arry[m] 就删除下标为m的 产生错误
stack.add(arry[i]);
show();
positon++;
ChangeNum++;
}
}
}
//判断页面是被包含
boolean juge(int k){
if(stack.contains(k))
{
return true;
}
return false;
}
void show(){
System.out.println("现有页面:");
for(int i=0;i<stack.size() ;i++)
{
System.out.println(stack.get(i));
}
System.out.println();
}
//找到要替换页面的位置
int change(){
Set<Integer> s = new HashSet<Integer>();
int k = positon-1;
while(s.size()<3)
{
s.add(arry[k]);
k--;
}
return k+1;
}
public static void main(String[] args) {
LRU l =new LRU();
l.lru();
System.out.println("----------页面置换次数"+l.ChangeNum+"------------");
}
}
此处难点在于向前看的时候,怎么确定物理块中的元素全部找到时,谁是最后找到的。
如果简单的只判断找到三个元素。
7 0 1 2 0 3 0 4,那么,0是最后找到的,所以0是最近最近未使用的页面。产生错误。
所以可以利用集合,集合中的元素是唯一的。只要判断集合长度>3,此时取出元素即可。
对应代码:
//找到要替换页面的位置
int change(){
Set<Integer> s = new HashSet<Integer>();
int k = positon-1;
while(s.size()<3)
{
s.add(arry[k]);
k--;
}
return k+1;
}
结果:
--------------------LRU算法---------------------
访问序列
7 0 1 2 0 3 0 4 2 3 0 3 2 1 2 0 1 7 0 1
现有页面:
7
0
1
2不在页面中,移除7
现有页面:
0
1
2
0在页面中,无需置换
3不在页面中,移除1
现有页面:
0
2
3
0在页面中,无需置换
4不在页面中,移除2
现有页面:
0
3
4
2不在页面中,移除3
现有页面:
0
4
2
3不在页面中,移除0
现有页面:
4
2
3
0不在页面中,移除4
现有页面:
2
3
0
3在页面中,无需置换
2在页面中,无需置换
1不在页面中,移除0
现有页面:
2
3
1
2在页面中,无需置换
0不在页面中,移除3
现有页面:
2
1
0
1在页面中,无需置换
7不在页面中,移除2
现有页面:
1
0
7
0在页面中,无需置换
1在页面中,无需置换
----------页面置换次数9------------
好的,over