赞
踩
掌握虚拟存储管理中页面置换算法的原理,设计恰当的数据结构和算法,模拟实现页面置换算法。
熟练掌握一种以上的开发工具,如C++、JAVA、Delphi、VB等,掌握基本的编程技巧,自由选择一种编程语言设计并实现实验内容。
需求分析:作业要访问的页面不在主存时,由缺页中断处理程序将所需的页面调入主存,若此时主存没有空闲物理块,则系统将按照一定的页面置换算法选择一些页面移除,以便装入所缺的页面。本实验模拟最近最久未用置换算法-LRU置换算法实现,是一种通用的广泛采用的有效算法。
算法设计思路:LRU置换算法每次都选择最久未使用的页面淘汰,即总是淘汰最后一次访问时间距当前时间间隔最长的页面。该算法的实现中,主要是标记在主存中的页面那个最近最久未被使用。本实验采用堆栈法的策略,按照页面被访问的时间次序依次将页面排列到堆栈中,因此每次最近被访问的页面总是在栈顶,而栈底的页面就是最近最久未使用的页面。当主存中没有空闲的物理块时,需要将栈底页面置换出去,其余页面依次下移,要访问的页面就可以添加到栈顶了。
流程图:
1.数据结构(页面对象):
public class Page {
int pagenum; //页面号
int time; //页面调入主存后存在的时间
}
2.算法实现代码:
public static void lru(List<Page> list, int p) { //淘汰页面集合 List<Page> out = new ArrayList<>(); //主存内页面集合,栈式存储 List<Page> base = new ArrayList<>(); //缺页中断次数 int count = 0; //命中次数 int n = 0; for (Page page : list) { //判断访问的页面是否已在主存 boolean flag = false; //如果页面已在主存中,无需淘汰页面,该页面序列之上的页面依次下移 for (Page pageIn : base) { if (page.pagenum == pageIn.pagenum) { for (int i = base.indexOf(pageIn); i+1 < base.size(); i++) { base.set(i,base.get(i+1)); flag = true; } //页面已在主存中,命中, n++; } } //如果页面不在主存 if (!flag) { //若此时主存未满则直接添加到堆栈中 if (base.size() < p) { base.add(page); } else { //若此时主存已满,则淘汰栈底元素,其余页面依次下移 out.add(base.get(0)); for (int i = 0; i + 1 < base.size(); i++) { base.set(i, base.get(i + 1)); } } //页面不在主存中,发生缺页中断 count++; } //要访问的页面置于栈顶 base.set(base.size()-1,page); System.out.print("各物理块页号情况:"); for (Page pageIn : base) { System.out.print(pageIn.pagenum + " "); } System.out.println(); } System.out.print("淘汰页号:"); for (Page page : out) { System.out.print(page.pagenum + " "); } System.out.println(); double qyl = (double) count/(double) list.size(); System.out.println("缺页中断次数:"+count+","+"缺页率为:"+ qyl); double mzl = (double) n/(double) list.size(); System.out.println("命中次数:"+n+","+"命中率:"+mzl); }
测试类:
public class Test {
public static void main(String[] args) {
List<Page> list = new ArrayList<>();
Scanner sc = new Scanner(System.in);
System.out.println("请输入访问页面的个数:");
int n = sc.nextInt();
System.out.println("请输入页面访问的序列:");
for (int i = 0; i < n; i++) {
int pagenum = sc.nextInt();
Page page = new Page(pagenum, 0);
list.add(page);
}
Page.lru(list, 3);
}
}
测试设计分配3个主存块,模拟访问13个页面,用表格来描述页面置换过程:
页面访问顺序 | 1 | 2 | 3 | 4 | 2 | 1 | 2 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 | 1 | 2 | 3 | 4 | 4 | 3 | 5 | 2 | 3 | 7 | 6 | |
2 | 2 | 3 | 4 | 2 | 1 | 1 | 2 | 3 | 5 | 2 | 3 | ||
3 | 4 | 2 | 1 | 2 | 2 | 3 | 5 | 2 | 3 | 7 | |||
1 | 1 | 1 | 2 | 3 | 4 | 4 | 3 | 5 | 2 | 3 | 7 | 6 | |
淘汰页面 | 1 | 3 | 4 | 1 | 5 | 2 | |||||||
缺页中断 | √ | √ | √ | √ | √ | √ | √ | √ | √ | ||||
命中 | √ | √ | √ | √ |
分析:访问页面时,页面未存在于主存中,发生缺页中断。(若此时主存空闲,直接添加堆栈。若此时主存已满,则需要淘汰栈底页面后调入新页面)
若页面已存在于主存中,则命中,需要将页面置于栈顶。
计算:缺页中断次数为9,缺页率9/13=69.2%;命中次数为4,命中率4/13=30.7%。
实验结果分析:根据结果分析,他们共享缓存器资源包子余量count,首先是p1被执行,包子加1,余量为1。接着c1被执行,包子减1,余量为0 。其余步骤类似,直至第11步,此时c1执行,发现缓存器中包子余量为0,进入等待状态并唤醒生产者。同理可知,如果某个时刻执行生产者进程时,发现缓存器中包子余量为3,则该生产者进程也会进入等待状态并唤醒消费者。
通过此次实验,加深了我对操作系统存储管理的认识,了解了操作系统中各种资源分配算法的实现,特别是对虚拟存储和页面置换的各个算法有了深刻的理解。
这次实验总体难度不是很大,需要实现的算法数目虽然不少,但基本思路较为相似,只要理解了每种算法的特点,理清思路实现起来也并不是很困难。本实验主要对LRU算法作了介绍。从页面数据结构的设计到算法的一步步实现,不断尝试、修改、优化,锻炼了我的编程能力,通过阅读课件再加上自己的理解,我了解了用堆栈法的设计思路。虽然方法名字叫堆栈法,但由于要频繁对栈底元素操作因此并没有真正用到栈,而是利用了栈先进后出的这一特点,方便我们找寻最近最久未使用的页面,感觉这个思路极其巧妙,设计中用到的方法和技巧体现出的很多思想值得我学习。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。