设计四:页面置换
设计内容:
设计一个程序,有一个虚拟存储区和内存工作区,实现下述三种算法中的任意两种,计算访问命中率(命中率=1-页面失效次数/页地址流长度)。附加要求:能够显示页面置换过程。
算法包括:先进先出的算法(FIFO)、最少使用算法(LFU)、最近未使用算法(NUR)
该系统页地址流长度为320,页面失效次数为每次访问相应指令时,该指令对应的页不在内存的次数。
程序首先用srand()和rand()函数分别进行初始化、随机数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算出相应的命中率。
通过随机数产生一个指令序列。共320条指令,指令的地址按下述原则生成:
(1)50%的指令是顺序执行的。
(2)25%的指令是均匀分布在前地址部分。
(3)25%的指令是均匀分布在后地址部分。
具体的实施方法如下:
在【0,319】的指令地址之间随机选取一起点m。
顺序执行一条指令,即执行地址为m+1的指令。
在前地址【0,m+1】中随机选取一条指令并执行,该指令的地址为m’。
顺序执行一条指令,其地址为m’+1。
在后地址【m’+2,319】中随机选取一条指令并执行。
重复步骤(1)-(5),直到320次指令。
将指令序列变换为页地址流。
设:
页面大小为1KB。
用户内存容量4页到32页。
用户虚存容量为32KB。
在用户虚存中,按每K存放10条指令虚存地址,即320条指令在虚存中的存放方式为:
第0条~9条指令为第0页(对应虚存地址为【0,9】)。
第10条~19条指令为第1页(对应虚存地址为【10,19】)。
……
第310条~319条指令为第31页(对应虚拟地址为【310,319】)。
按以上方式,用户指令可组成32页。
计算每种算法在不同内存容量下的命中率。
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;
public class R{
public static void main (String[]args)
{
ArrayList<Integer> pageList=new ArrayList<Integer>();//创建数组
Scanner scanner=new Scanner(System.in); //输入对象
System.out.print("输入物理块数: ");
int blocknum=scanner.nextInt(); //物理块数输入
Random random = new Random(); //创建随机数对象
while(pageList.size()<320) //输入320条指令
{
int m = random.nextInt(320)+1; //顺序执行
int M=m/10; //每10条指令为一个页面
pageList.add(M);
int k=random.nextInt(m+1)+1; //前地址部分
int K=k/10;
pageList.add(K);
int p=random.nextInt(320-k-1); //后地址部分
int P=p/10;
pageList.add(P);
}
/*
System.out.print("输入页面访问序列: ");
int page=scanner.nextInt(); //第一个页面输入
while(page!=-1) //当输入页面数不为-1时,输入循环
{
pageList.add(page); //将输入的页面加入到数组中
page=scanner.nextInt();
}
*/
System.out.println("请选择需要的算法:1.FIFO算法 2.LRU算法");
while(true)
{
int choose=scanner.nextInt();//选择算法
switch (choose)
{
case 1:FIFO(blocknum,pageList);break; //将物理块数,和数组传给FIFO方法
case 2:LRU(blocknum,pageList);break;
case 0:System.exit(0);break;
}
}
}
public static void FIFO(int blocknum,ArrayList pageList) //方法,传入参数物理块数,和数组
{
FIFO fifo=new FIFO(blocknum,pageList);//类声明对象fifo,调用类FIFO的构造方法
fifo.deal();
System.out.println("缺页次数: "+fifo.getLackPage());
System.out.println("命中率: "+(1-fifo.getLackPage()/(float)fifo.getNumber())*100+"%");
}
public static void LRU (int blocknum,ArrayList pageList)
{
LRU lru=new LRU(blocknum,pageList);
lru.deal();
System.out.println("缺页次数: "+lru.getLackpage());
System.out.println("命中率: "+(1-lru.getLackpage()/(float)lru.getNumber())*100+"%");
}
}
class FIFO
{
private int blocknum; //物理块数
private ArrayList<Integer>page;//整型数组,访问页面
private int lacknum;//缺页次数
public FIFO(int blocknum,ArrayList page)//构造方法
{
this.blocknum=blocknum;
this.page=page;
this.lacknum=0;
}
public int getLackPage()//获取缺页次数
{
return this.lacknum;
}
public int getNumber()//获取访问页面数量
{
return this.page.size();
}
public void output(int []block)//输出物理块中的页面
{
for(int i=0;i<block.length;i++)
{
if(block[i]!=-1)
System.out.print(block[i]+" ");
}
System.out.println("");
}
public void deal()
{
int first=0;
int count=0;
int []block=new int[this.blocknum];//创建物理块数组
for(int i=0;i<this.blocknum;i++) //初始化数组,内置为-1
block[i]=-1;
for(int i=0;i<this.page.size();i++)//在页面总数内逐一比较
{
boolean exists=false;//定义变量并赋值false,表示“假”
//内存中已存在该页面
for(int j=0;j<block.length;j++)//物理块数组长度
if(block[j]==this.page.get(i))//一开始初始化都为-1,第一个页面跟所有物理块比较,
{
exists=true; //没有结果所以exists的值没有改变,缺页数+1
break; //当内存为满,若有页面命中,exists置为“真”,并跳出搜索循环
}
//............................................
if(exists) //若是命中,则跳出该次循环,进入下次循环
{
continue;
}
else
{
this.lacknum++;//缺页数++
}
//............................................
//内存中不存在该页面
if(count<this.blocknum) //假如物理块中页面未满,则按顺序放入
{
block[count]=this.page.get(i);
count++;
}
else //内存已满
{
block[first]=this.page.get(i);//将需要置换的页面放到第一位
first++; //下标+1
if(first>=this.blocknum) //当下标等于物理块时,重置为0,即第一位
first=0;
}
output(block);
}
}
}
class LRU
{
private int blocknum; //物理块数变量
private ArrayList<Integer>page; //创建数组
private int lacknum; //缺页次数
public LRU(int blocknum,ArrayList page)
{
this.blocknum=blocknum;
this.page=page;
this.lacknum=0;
}
public int getLackpage() {
return this.lacknum;
}
public int getNumber(){
return this.page.size();
}
public void output(ArrayList block)
{
int size=block.size();
for(int i=0;i<size;i++)
{
System.out.print(block.get(i)+" ");
}
System.out.println("");
}
public void deal()
{
ArrayList<Integer> block=new ArrayList<Integer>();
for(int i=0;i<this.page.size();i++)
{
boolean exists=false;
int j;
for(j=0;j<block.size();j++)
if(this.page.get(i)==block.get(j))//该页面在物理块中寻找相等的页面
{
exists=true; //找到后修改exists的值
break; //跳出循环
}
if(exists) //若为真
block.remove(j); //将该页面所在的物理块中的位置删除
else
{
this.lacknum++;
if(block.size()>=this.blocknum) //当物理块长度达到最大时
block.remove(0); //移除第一位的页面,那么后面的页面会向前移动
}
block.add(this.page.get(i)); //将新加入的页面放入数组最后
output(block);
//由于该block是由ArrayList声明的对象,ArrayList的数组在删除一个元素后,后面的元素会向前移
//利用这个特性,可以将第一位设置为最久未使用的页面,即若没有命中,那么就是一个FIFO算法,
//若命中,则删除原页面所在的位置,并加入到最后,即最新使用。
}
}
}
如有错误,欢迎指出