操作系统实习

设计四:页面置换

设计内容:

    设计一个程序,有一个虚拟存储区和内存工作区,实现下述三种算法中的任意两种,计算访问命中率(命中率=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算法,
				//若命中,则删除原页面所在的位置,并加入到最后,即最新使用。
		}  
	}
}
如有错误,欢迎指出
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值