操作系统实习

设计四:页面置换

设计内容:

    设计一个程序,有一个虚拟存储区和内存工作区,实现下述三种算法中的任意两种,计算访问命中率(命中率=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
    评论
(1)通过随机数产生一个指令序列320指令指令地址下述原则生成: ①、 50%的指令是顺序执行的; ②、 25%的指令是均匀分布在前地址部分; ③、 25%的指令是均匀分布在后地址部分。 具体的实施方法是: ① 在[0,319]的指令地址之间随机选取一起点m; ② 顺序 执行一指令,即执行地址为m+1的指令; ③ 在前地址[0,m+1]中随机选取一指令并执行,该指令地址为m’; ④ 顺序执行一指令,其地址为m’+1; ⑤ 在后地址[m’+2,319]中随机选取一指令并执行; ⑥ 重复上述步骤,直至执行320指令。 (2) 将指令序列变换成页地址流 设:①页面大小为1K; ②用户内存容量为4页到32页; ③用户虚存容量为32K; 在用户虚存中,按每K存放10指令排列虚存地址,即320指令在虚存中的存放方式为: 第0~第9指令为第0页(对应的虚存地址为[0,9]); 第10~第19指令为第1页(对应的虚存地址为[10,19]); . 第310~第319指令为第31页(对应的虚存地址为[310,319]); 按以上方式,用户指令可组成32页。 (3) 计算并输出下述各种算法在不同的内存容量下的命中率。 ① 先进先出的算法(FIFO); ② 最近最少使用算法(LRR); ③ 最佳淘汰法(OPT):先淘汰最不常用的页地址; ④ 最少访问页面算法(LFR); ⑤ 最近不经常使用算法(NUR)。 其中③和④为选择内容。 命中率=1-(页面失效次数)/(页地址流长度) 在本实验中,页地址流的长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不在内存的次数。
下面是一个简单的Java实现的模拟操作系统实习存储管理的代码示例: ```java import java.util.ArrayList; import java.util.List; class Process { private int pid; // 进程ID private int size; // 进程大小 public Process(int pid, int size) { this.pid = pid; this.size = size; } public int getPid() { return pid; } public int getSize() { return size; } } class MemoryBlock { private int start; // 起始地址 private int size; // 块大小 private boolean allocated; // 是否已分配 public MemoryBlock(int start, int size) { this.start = start; this.size = size; this.allocated = false; } public int getStart() { return start; } public int getSize() { return size; } public boolean isAllocated() { return allocated; } public void allocate() { allocated = true; } public void deallocate() { allocated = false; } } class MemoryManager { private List<MemoryBlock> memoryBlocks; public MemoryManager(int totalSize) { memoryBlocks = new ArrayList<>(); memoryBlocks.add(new MemoryBlock(0, totalSize)); } public void allocate(Process process) { for (MemoryBlock block : memoryBlocks) { if (!block.isAllocated() && block.getSize() >= process.getSize()) { block.allocate(); System.out.println("Process " + process.getPid() + " allocated at address " + block.getStart()); return; } } System.out.println("Process " + process.getPid() + " cannot be allocated"); } public void deallocate(Process process) { for (MemoryBlock block : memoryBlocks) { if (block.isAllocated() && block.getStart() == process.getPid()) { block.deallocate(); System.out.println("Process " + process.getPid() + " deallocated"); return; } } System.out.println("Process " + process.getPid() + " not found"); } } public class StorageManagementSimulation { public static void main(String[] args) { MemoryManager memoryManager = new MemoryManager(1000); Process p1 = new Process(1, 200); memoryManager.allocate(p1); Process p2 = new Process(2, 500); memoryManager.allocate(p2); Process p3 = new Process(3, 300); memoryManager.allocate(p3); memoryManager.deallocate(p2); Process p4 = new Process(4, 400); memoryManager.allocate(p4); } } ``` 在这个示例中,模拟了一个简单的存储管理系统。`Process` 类表示一个进程,具有进程ID和进程大小。`MemoryBlock` 类表示内存块,具有起始地址、块大小和分配状态。`MemoryManager` 类是存储管理器,负责分配和释放内存块。 在 `main()` 方法中,首先创建了一个总大小为1000的内存管理器 `MemoryManager`。然后分别创建了4个进程 `p1`、`p2`、`p3`、`p4`,并通过 `allocate()` 方法将它们分配到内存中。其中,`p2` 进程通过 `deallocate()` 方法被释放出内存,然后 `p4` 进程再次被分配到内存中。 运行代码将输出以下结果: ``` Process 1 allocated at address 0 Process 2 allocated at address 200 Process 3 allocated at address 700 Process 2 deallocated Process 4 allocated at address 200 ``` 这个示例展示了一个简单的内存分配和释放过程,通过模拟操作系统实习存储管理的基本功能。请注意,这只是一个简化的示例,实际的存储管理系统可能会更复杂。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值