先看下题目要求:
1实验目的
通过对页面、页表、地址转换和页面置换过程的模拟,加深对请求调页系统的原理和实现过程的理解。
2实验内容
(1)假设每个页面中可存放10条指令,分配给一作业的内存块数为4。
(2)模拟一作业的执行过程。该作业共有320条指令,即它的地址空间为32页,目前它的所有页都还未调入内存。在模拟过程中,如果所访问的指令已经在内存中,则显示其物理地址,并转下一条指令。如果所访问的指令还未装入内存,则发生缺页,此时需记录缺页的次数,并将相应页调入内存。如果4个内存块中均已装入该作业,则需进行页面置换。最后显示其物理地址,并转下一条指令。在所有320条指令执行完毕后,请计算并显示作业运行过程中发生的缺页率。
(3)置换算法:请分别考虑OPT、FIFO和LRU算法。
(4)作业中指令的访问次序按下述原则生成:
•50%的指令是顺序执行的。
•25%的指令是均匀分布在前地址部分。
•25%的指令时均匀分布在后地址部分。
3实验结果(给出编写的程序源代码和运行结果的截图)
这个题目需要注意的是:
该作业的320条指令是可以重复的。你需要一个随机出来这320条指令,将它们除以10就代表了将要调用的页,也就是0~31页。随着320指令的执行,会不停的调用这32页。
因为有四个内存块,所以需要定义四个块来存放调用的页面
package yeReplace; /* * 内存中的物理块 */ public class BLOCK { public int pageNum; //页号 public int accessed; //页的访问字段,记录页有多久没有被访问,用于opt置换 public BLOCK() { super(); } public BLOCK(int pageNum, int accessed) { super(); this.pageNum = pageNum; this.accessed = accessed; } @Override public String toString() { return "BLOCK [pageNum=" + pageNum + ", accessed=" + accessed + "]"; } }
这是主类
package yeReplace; import java.io.BufferedReader; import java.io.FileFilter; import java.io.IOException; import java.io.InputStreamReader; public class PageAPP { public static final int bSIZE = 4; static int pc; //程序计数器,用来记录指令的序号 static int n; //缺页计数器,用来记录缺页的次数 static int[] temp = new int[320]; //用来存放产生的320条随机数 static BLOCK[] block; static int i; //FIFO中选择的物理块 //初始化 public static void init() { block = new BLOCK[bSIZE]; pc = n = 0; for (int i = 0; i < bSIZE; i++) { BLOCK aa = new BLOCK(-1,0); block[i] = aa; } } //查找物理块中是否有该页面 public static int findExits(int page){ for (int i = 0; i < bSIZE; i++) { if (block[i].pageNum == page) { return i; //物理块中是否含有要调用的页curPage,如果有返回其位置i } } return -1; } //查找空闲物理块 public static int findSpace() { for (int i = 0; i < bSIZE; i++) { if (block[i].pageNum == -1) { return i; //存在空闲物理块的话就返回它的位置 } } return -1; } //选择应予置换的页面 public static int findPage(){ int position = 0; for (int i = 1; i < bSIZE; i++) { if (block[i].accessed > block[i-1].accessed){ position = i; } } return position; } //显示 public static void display(){ for (int i = 0; i < bSIZE; i++) { if (block[i].pageNum!=-1) { if (block[i].pageNum<10) { System.out.print("0" + block[i].pageNum+ " "); }else { System.out.print(block[i].pageNum + " "); } } } System.out.println(""); } //产生的320条随机数,可以重复 public static void suijishu() throws IOException{ int flag = 0; pc= getInt(); //第一条数据是自己输入的 System.out.println("按照要求产生的随机数:"); for (int i = 0; i < 320; i++) { temp[i] = pc; int a = (int)(java.lang.Math.random()*320); if (flag%2==0) { //50%几率顺序执行 pc = ++pc%320; }else if (flag == 1) { //25%几率向下执行 pc = a%(pc-1); }else if (flag == 3) { //25%几率向上执行 pc = pc+1+(a%(320-(pc+1))); } flag = ++flag%4; //flag的取值为0、1、2、3 if (temp[i]<10) { System.out.print("00"+ temp[i] + " "); }else if (temp[i]<100) { System.out.print("0" + temp[i] + " "); }else { System.out.print(temp[i] + " "); } if (i % 10 == 0) { System.out.println(""); } } System.out.println(""); } //显示调用的页面队列 public static void pageString(){ for (int i = 0; i < 320; i++) { int a = temp[i]/10; //a代表页号,将temp中的指令转化为调用的页 if (a<10) { System.out.print("0"+a+" "); }else { System.out.print(a + " "); } if ((i+1)%10 == 0) { System.out.println(""); } } } //OPT算法 public static void OPT(){ int exist,position,space; int curPage; for (int i = 0; i < 320; i++) { pc = temp[i]; curPage = pc/10; //调用的页 exist = findExits(curPage); if (exist == -1) { space = findSpace(); if (space != -1) { //存在空的物理块 block[space].pageNum = curPage; display(); n = n+1; }else { //不存在空的物理块 for (int j = 0; j < bSIZE; j++) { for (int j2 = i; j2 < 320; j2++) { if (block[j].pageNum!=temp[j2]/10) { BLOCK mm = new BLOCK(block[j].pageNum,1000); block[j] = mm; }else { BLOCK mm = new BLOCK(block[j].pageNum,j2); block[j] = mm; break; } } } position = findPage(); block[position] = new BLOCK(curPage, 0); display(); n++; } } } System.out.println("缺页次数:" + n); int answer = (n * 100)/320; System.out.println("缺页率:" + answer + "%"); } //FIFO的选择页方法 public static int findBlock(){ if (i<bSIZE) { return i++; }else { i=0; return i++; } } //FIFO public static void FIFO(){ int exist,position,space; int curPage; for (int i = 0; i < 320; i++) { pc = temp[i]; curPage = pc/10; exist = findExits(curPage); if (exist == -1) { space = findSpace(); if (space != -1) { //存在空的物理块 block[space].pageNum = curPage; display(); n = n+1; }else { //不存在空的物理块 position = findBlock(); //与RTO不同的地方 block[position] = new BLOCK(curPage, 0); display(); n++; } } } System.out.println("缺页次数:" + n); int answer = (n * 100)/320; System.out.println("缺页率:" + answer + "%"); } //主函数 public static void main(String[] args) throws IOException{ init(); System.out.println("输入第一次执行的指令指令号(0~320):"); suijishu(); while(true){ System.out.println("输入指令:"); System.out.println("1.显示对应的调用序列:"); System.out.println("2.退出"); int choice = getInt(); switch(choice){ case 1: System.out.println("对应的调用队列:"); pageString(); System.out.println("选择置换算法:"); System.out.println("1.最佳置换算法:"); System.out.println("2.先进先出算法:"); int choice2 = getInt(); switch (choice2) { case 1: System.out.println("最佳置换算法:"); System.out.println("=============="); OPT(); break; case 2: System.out.println("先进先出算法:"); System.out.println("=============="); FIFO(); break; case 3: System.exit(0); break; default: break; } break; case 2: System.exit(0); break; } } } //程序输入方法 public static String getString() throws IOException{ InputStreamReader in = new InputStreamReader(System.in); BufferedReader buff = new BufferedReader(in); String s = buff.readLine(); return s; } public static int getInt() throws IOException { String s = getString(); return Integer.parseInt(s); } }