原理:
最近最久未使用(LRU)的页面置换算法,是根据页面调入内存后的使用情况做出决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。
- 该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t。
- 当需要淘汰一个页面时,选择现有也面中t值最大的,即最近最久未使用的页面予以淘汰。
Java代码实现:
-
页表类:
public class Page {
//页表
private int id;//页号
private int adr;//物理块号
private int t;//页面自上次被访问以来所经历的时间
private boolean m;//0停止数
private boolean s;//0空闲 1调入
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAdr() {
return adr;
}
public void setAdr(int adr) {
this.adr = adr;
}
public int getT() {
return t;
}
public void setT(int t) {
this.t = t;
}
public boolean isM() {
return m;
}
public void setM(boolean m) {
this.m = m;
}
public boolean isS() {
return s;
}
public void setS(boolean s) {
this.s = s;
}
public Page(int id, int adr, int t, boolean m, boolean s) {
super();
this.id = id;
this.adr = adr;
this.t = t;
this.m = m;
this.s = s;
}
public Page() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Page [id=" + id + ", adr=" + adr + ", t=" + t + ", m=" + m + ", s=" + s + "]";
}
}
-
测试类:
import java.util.ArrayList;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
int n=0;//表示物理块数
Scanner sc =new Scanner(System.in);
System.out.println("请输入该进程拥有的物理块数!");
n=sc.nextInt();
int [] b=new int[n];
System.out.println("请输入"+n+"个物理块号!");
for (int i = 0; i < b.length; i++) {
b[i]=sc.nextInt();
}
ArrayList<Page> list=new ArrayList<>();
int m=-1;
int i=1;
System.out.println("请输入页号走向(输入0结束):");
while(m!=0) {
System.out.print("页面序号"+i+":");
m=sc.nextInt();
Page p=new Page();
p.setId(i);
p.setAdr(m);
p.setM(true);
if(m==0) {
p.setM(false);
}
list.add(p);
i++;
}
//System.out.println(list.size());
LRU(b,list);
}
private static void LRU(int[] b, ArrayList<Page> list) {
// System.out.println(list);
System.out.println("置换情况如下:");
float que=0;
for (Page page:list) {
//判断是否最后一页:结束页
if(page.isM()==true) {
for (int bi=0;bi<b.length;bi++) {
boolean jump=false;
for(int existB:b){
if(page.getAdr()==existB) {
for(Page existp:list) {
if(existp.isS()==true&existp.getAdr()==page.getAdr()) {
list.get(existp.getId()-1).setS(false);
list.get(existp.getId()-1).setT(0);
}
}
list.get(page.getId()-1).setS(true);
list.get(page.getId()-1).setT(1);
for(int j=1;j<=bi;j++) {//t++
list.get(page.getId()-1-bi).setT(list.get(page.getId()-1-bi).getT()+1);
}
// list.get(page.getId()-2).setT(list.get(page.getId()-2).getT()+1);
// list.get(page.getId()-3).setT(list.get(page.getId()-3).getT()+1);
System.out.println("内存中有"+page.getAdr()+"号页面,无须缺页中断!");
jump=true;
break;
}
}
if(jump) {
break;
}
if(b[bi]==0) {
list.get(page.getId()-1).setS(true);
list.get(page.getId()-1).setT(1);
for(int j=1;j<=bi;j++) {
list.get(page.getId()-1-j).setT(list.get(page.getId()-1-j).getT()+1);
}
b[bi]=page.getAdr();
System.out.println("发生缺页中断,但内存中有空闲区,"+page.getAdr()+"号页面直接调入!");
que++;
break;
}else {//需要调出
if(bi==(b.length-1)) {
int t=0;
int export = 0;
for(Page pageMax:list) {
if(pageMax.isS()==true&pageMax.getT()>t) {
t=pageMax.getT();
export=pageMax.getId()-1;
}
}
for(int i=0;i<b.length;i++) {
if(b[i]==list.get(export).getAdr()) {
b[i]=page.getAdr();
}
}
list.get(export).setT(0);
list.get(export).setS(false);
list.get(page.getId()-1).setS(true);
list.get(page.getId()-1).setT(1);
for(int j=1;j<=bi;j++) {
list.get(page.getId()-1-bi).setT(list.get(page.getId()-1-bi).getT()+1);
}
System.out.println("发生缺页中断,将"+list.get(export).getAdr()+"号页面调出,"+page.getAdr()+"号装入!");
que++;
break;
}
}
}
}else {
// System.out.println("00");
break;
}
}
System.out.println("页号"+(list.size()-1)+"个,缺页中断"+que+"次,缺页率:"+(que/(list.size()-1)*100)+"%");
}
}