请求页式存储管理中页面置换算法的java实现

2019-04-14 16:25发布

        存储管理的主要功能之一是合理地分配空间。请求页式管理是一种常用的虚拟存储管理技术。
        模拟页式虚拟存储管理中硬件的地址转换和缺页中断,并用先进先出调度算法(FIFO)处理缺页中断。
        (1)为了装入一个页面而必须调出一页时,如果被选中调出的页面在执行中没有修改过,则不必把该页重新写到磁盘上(因磁盘上已有副本)。因此,在页表中可以增加是否修改过的标志,当执行“存”指令、“写”指令时把对应页的修改标志置成“1”表示该页修改过,否则为“0”表示该页未修改过。页表格式如表3-1所示。         (2)设计一个地址转换程序来模拟硬件的地址转换和缺页中断。当访问的页在主存时则形成绝对地址,但不去模拟指令的执行,可用输出转换后的绝对地址来表示一条指令已完成。当访问的页不在主存时则输出“*该页页号”来表示硬件产生了一次缺页中断。模拟地址转换的程序流程如图3-1所示。         (3)编制一个FIFO页面调度程序。FIFO页面调度算法总是先调出作业中最先进入主存的那一页,因此,可以用一个数组来构成页号队列。数组中每个元素是该作业已在主存的页面号,假定分配给作业的主存块数为m,且该作业开始的m页已装入主存,则数组可由m个元素组成:
P[0],P[1],…,P[m-1]
它们的初值为
P[0]∶=0,P[1]∶=1,…,P[m-1]∶= m-1
用一指针k指示当要装入新页时应调出的页在数组的位置,k的初值为“0”。         当产生缺页中断后,操作系统总是选择P[k]所指出的页面调出,然后执行
P[k]∶=要装入的新页页号
k∶=(k+1)mod m
在实验中不必实际地启动磁盘执行调出一页和装入一页的工作,而用输出“OUT调出的页号”和“IN要装入的新页页号”来模拟一次调出和装入的过程。模拟程序的流程见图3-1。
        (4)假定主存的每块长度为1024个字节,现有一个共7页的作业,其副本已在磁盘上。系统为该作业分配了4块主存块,且该作业的第0页至第3页已经装入主存,其余3页尚未装入主存,该作业的页表见表3-2。 如果该作业依次执行的指令序列如表3-3所示。         依次执行上述的指令序列来调试你所设计的程序(仅模拟指令的执行,不必考虑指令序列中具体操作的执行)
        (5)为了检查程序的正确性,可自行确定若干组指令序列,运行设计的程序,核对执行结果。 主类 package report; import java.util.ArrayList; import java.util.List; public class N3 { private static int L; private static int j; private static int m = 4; private static int k = 0; private static int P[] = { 0, 1, 2, 3 }; private static List pageList = new ArrayList(); private static List cmdList = new ArrayList(); public static void main(String[] args) { Page page0 = new Page(0, 1, 5, 0, "011"); Page page1 = new Page(1, 1, 8, 0, "012"); Page page2 = new Page(2, 1, 9, 0, "013"); Page page3 = new Page(3, 1, 1, 0, "021"); Page page4 = new Page(4, 0, -1, 0, "022"); Page page5 = new Page(5, 0, -1, 0, "023"); Page page6 = new Page(6, 0, -1, 0, "121"); pageList.add(page0); pageList.add(page1); pageList.add(page2); pageList.add(page3); pageList.add(page4); pageList.add(page5); pageList.add(page6); Cmd cmd0 = new Cmd("+", 0, "070"); Cmd cmd1 = new Cmd("+", 1, "050"); Cmd cmd2 = new Cmd("x", 2, "015"); Cmd cmd3 = new Cmd("存", 3, "021"); Cmd cmd4 = new Cmd("取", 0, "056"); Cmd cmd5 = new Cmd("-", 6, "040"); Cmd cmd6 = new Cmd("移位", 4, "053"); Cmd cmd7 = new Cmd("+", 5, "023"); Cmd cmd8 = new Cmd("存", 1, "037"); Cmd cmd9 = new Cmd("取", 2, "078"); Cmd cmd10 = new Cmd("+", 4, "001"); Cmd cmd11 = new Cmd("存", 6, "084"); cmdList.add(cmd0); cmdList.add(cmd1); cmdList.add(cmd2); cmdList.add(cmd3); cmdList.add(cmd4); cmdList.add(cmd5); cmdList.add(cmd6); cmdList.add(cmd7); cmdList.add(cmd8); cmdList.add(cmd9); cmdList.add(cmd10); cmdList.add(cmd11); printPageList(); while (!cmdList.isEmpty()) { // 取指令中访问的页号=>L L = cmdList.get(0).getPage(); while (true) { // 查页表 // 页标志=1 if (pageList.get(L).getFlag() == 1) { // 形成绝对地址 int absoluteAddress = pageList.get(L).getPiece() * 1024 + Integer.parseInt(cmdList.get(0).getAddressInPage()); // 是”存”指令 if (cmdList.get(0).getOperation().equalsIgnoreCase("存")) { // 置L页修改标志”1” pageList.get(L).setModify(1); } else { } // 输出绝对地址 System.out.println("运行指令:" + cmdList.get(0).getOperation() + " 页号:" + pageList.get(L).getPage() + " 页内地址:" + cmdList.get(0).getAddressInPage() + " 绝对地址:" + absoluteAddress + " 页标志:" + pageList.get(L).getFlag() + " 主存块号:" + pageList.get(L).getPiece() + " 页修改标志:" + pageList.get(L).getModify() + " 页在磁盘上的位置:" + pageList.get(L).getPositionInDisk()); } // 页标志!=1 else { System.out.println(); System.out.println("内存中找不到页" + L); j = P[k]; int tempPiece = pageList.get(j).getPiece(); if (pageList.get(j).getModify() == 1) { System.out.println("页" + 3 + "写到外存"); } else { } System.out.println("内存调出页" + j); pageList.get(j).setFlag(0); pageList.get(j).setModify(0); pageList.get(j).setPiece(-1); System.out.println("内存调入页" + L); pageList.get(L).setFlag(1); pageList.get(L).setPiece(tempPiece); P[k] = L; k = (k + 1) % m; printPageList(); continue; } // 当前指令结束 cmdList.remove(0); break; } } } private static void printPageList() { System.out.println("=========================================================================="); System.out.print("页号 标志 主存块号 修改标志 在磁盘上的位置 "); // finish链 for (Page page : pageList) System.out.println(page.getPage() + " " + page.getFlag() + " " + page.getPiece() + " " + page.getModify() + " " + page.getPositionInDisk()); System.out.println("=========================================================================="); } } page类 package report; public class Page { private int page; private int flag; private int piece; private int modify; private String positionInDisk; public Page(int page, int flag, int piece, int modify, String positionInDisk) { this.page = page; this.flag = flag; this.piece = piece; this.modify = modify; this.positionInDisk = positionInDisk; } public int getPage() { return page; } public void setPage(int page) { this.page = page; } public int getFlag() { return flag; } public void setFlag(int flag) { this.flag = flag; } public int getPiece() { return piece; } public void setPiece(int piece) { this.piece = piece; } public int getModify() { return modify; } public void setModify(int modify) { this.modify = modify; } public String getPositionInDisk() { return positionInDisk; } public void setPositionInDisk(String positionInDisk) { this.positionInDisk = positionInDisk; } }  运行过程部分截图