编程实现LRU算法或CLOCK/改进算法等置换算法(二选一),模拟实现虚拟存储器的地址变换过程。
理解虚拟存储器的地址变换过程;
设计用于模拟快表、页表、地址变换所用的寄存器的数据结构;
编制页表的初始信息文件,举例说明文件中具有的信息:共有5块,每块的状态、在内存和外存的起始地址等。
编程实现虚拟存储器地址变换算法程序,动态输入所要访问的逻辑地址,变换过程文字描述以及变换后的物理地址;
测试:输入有效、无效地址,测试程序的正确性和错误处理能力。
PageTable.java
package OperatingSystem.experiment2.AddressTransformation; public class PageTable { private int PageNumber; //页号 private int blockNumber; //物理块号 private int state=0; //状态位P 1为在内存,0为在外存 private int visited=0; //访问位A 该页被访问的次数 private int revise=0; //修改位M 1为该页被修改,0为该页未被修改 private int ExternalStorageAddress; //外存地址 public int getPageNumber() { return PageNumber; } public void setPageNumber(int pageNumber) { PageNumber = pageNumber; } public int getBlockNumber() { return blockNumber; } public void setBlockNumber(int blockNumber) { this.blockNumber = blockNumber; } public int getState() { return state; } public void setState(int state) { this.state = state; } public int getVisited() { return visited; } public void setVisited(int visited) { this.visited = visited; } public int getRevise() { return revise; } public void setRevise(int revise) { this.revise = revise; } public int getExternalStorageAddress() { return ExternalStorageAddress; } public void setExternalStorageAddress(int externalStorageAddress) { ExternalStorageAddress = externalStorageAddress; } public PageTable(int PageNumber, int externalStorageAddress){ this.PageNumber=PageNumber; this.blockNumber=externalStorageAddress; this.ExternalStorageAddress=externalStorageAddress; } }
CrossedException.java
package OperatingSystem.experiment2.AddressTransformation; public class CrossedException extends Exception{ public CrossedException(){ super("越界中断"); } public CrossedException(String message){ super(message); } }
Conversion.java
package OperatingSystem.experiment2.AddressTransformation; import java.util.ArrayList; import java.util.Scanner; //页表中5块,内存中4块,快表中3块 public class Conversion { int P; int d; int fastTable[];//快表 ArrayList <PageTable> arrayList1=new ArrayList<>();//存页表 ArrayList <PageTable> arrayList=new ArrayList<>(); //内存 Scanner scanner=new Scanner(System.in); public Conversion(){ fastTable=new int[3]; for (int i=0;i<fastTable.length;i++){ fastTable[i]=-1; } for (int i=0;i<5;i++){ PageTable pageTable=new PageTable(i,scanner.nextInt()); arrayList1.add(pageTable); } } public void exchange(int address)throws CrossedException{ P=address/(int) Math.pow(2,10); d=address%(int) Math.pow(2,10); System.out.println("页号为"+P); if (P>=arrayList1.size()){ throw new CrossedException(); } } public void Retrieval(){ boolean flag=false; for (int i=0;i<fastTable.length;i++){ if (P==fastTable[i]){ changeAM(Find(arrayList1,P)); flag=true; } } if (!flag){ System.out.println("页表项不在快表中"); if (arrayList1.get(Find(arrayList1,P)).getState()==0){ System.out.println("页不在内存中"); MissPage(); } changeFastTable(); changeAM(Find(arrayList1,P)); } } public int Find(ArrayList<PageTable> arrayList,int pageNumber){ for (int i=0;i<arrayList.size();i++){ if (arrayList.get(i).getPageNumber()==pageNumber){ return i; } } return -1; } public void changeFastTable(){ System.out.println("修改快表"); int count=0; for (int i=0;i<fastTable.length;i++){ if (fastTable[i]!=-1){ count++; } } if (count==fastTable.length){ printFastTable(); System.out.println("快表已满,需要替换"); int min=0; for (int i=1;i<fastTable.length;i++){ if (arrayList1.get(Find(arrayList1,fastTable[min])).getVisited()>arrayList1.get(Find(arrayList1,fastTable[i])).getVisited()){ min=i; } } System.out.println("页号"+fastTable[min]+"在快表中被置换掉"); fastTable[min]=P; }else { fastTable[count]=P; } } public void changeAM(int i){ arrayList1.get(i).setVisited(arrayList1.get(i).getVisited()+1); System.out.println("是否对此页进行修改?y/n"); switch (scanner.next()){ case "y": arrayList1.get(i).setRevise(1); break; case "n": break; } printFastTable(); printPageTable(); printMemory(); physicsAD(); } public void printFastTable(){ System.out.println("------------------------------------------"); System.out.println("输出快表:"); System.out.println("页号"+" "+"物理块号"+"\t"+"状态位P"+"\t"+"访问字段A"+" "+"修改位M"+"\t"+"外存地址"); for (int i=0;i<fastTable.length;i++) { int a = fastTable[i]; if (a != -1) { System.out.println(arrayList1.get(a).getPageNumber() + "\t\t" + arrayList1.get(a).getBlockNumber() + "\t\t" + arrayList1.get(a).getState() + "\t\t" + arrayList1.get(a).getVisited() + "\t\t\t" + arrayList1.get(a).getRevise() + "\t\t" + arrayList1.get(a).getExternalStorageAddress()); } } } public void printPageTable(){ System.out.println("------------------------------------------"); System.out.println("输出页表:"); System.out.println("页号"+" "+"物理块号"+"\t"+"状态位P"+"\t"+"访问字段A"+" "+"修改位M"+"\t"+"外存地址"); for (int i=0;i<arrayList1.size();i++){ System.out.println(arrayList1.get(i).getPageNumber() + "\t\t" + arrayList1.get(i).getBlockNumber() + "\t\t" + arrayList1.get(i).getState() + "\t\t" + arrayList1.get(i).getVisited() + "\t\t\t" + arrayList1.get(i).getRevise() + "\t\t" + arrayList1.get(i).getExternalStorageAddress()); } } public void printMemory(){ System.out.println("------------------------------------------"); System.out.println("在内存的页号"); for (int i=0;i<arrayList.size();i++){ System.out.print(arrayList.get(i).getPageNumber()+"\t"); } System.out.println(); } public void MissPage(){ System.out.println("------------------------------------------"); System.out.println("发生缺页中断"); System.out.println("保留CPU现场"); System.out.println("从外存中找到缺页"); if (arrayList.size()>=4){ System.out.println("内存已满,将访问次数最少的页换出内存"); printMemory(); int min=0; for (int i=0;i<arrayList.size();i++){ if (arrayList1.get(Find(arrayList1,arrayList.get(min).getPageNumber())).getVisited()>arrayList1.get(Find(arrayList1,arrayList.get(i).getPageNumber())).getVisited()){ min=i; } } int a=arrayList.get(min).getPageNumber(); System.out.println("页号"+a+"被换出内存"); arrayList1.get(Find(arrayList1,a)).setBlockNumber(arrayList1.get(Find(arrayList1,a)).getExternalStorageAddress()); arrayList1.get(Find(arrayList1,a)).setVisited(0); arrayList1.get(Find(arrayList1,a)).setState(0); arrayList1.get(Find(arrayList1,P)).setState(1); if (arrayList1.get(Find(arrayList1,a)).getRevise()==1){ System.out.println(a+"页被修改过"); System.out.println("将该页写回外存"); arrayList1.get(Find(arrayList1,a)).setRevise(0); } arrayList.set(min,arrayList1.get(Find(arrayList1,P))); printMemory(); } readIn(); } public void readIn(){ System.out.println("OS命令CPU从外存中读缺页"); System.out.println("启动I/O硬件"); System.out.println("将一页从外存换入内存"); arrayList1.get(Find(arrayList1,P)).setState(1); System.out.println("系统分配内存块号"); System.out.println("系统分配的内存块号为:"); arrayList1.get(Find(arrayList1,P)).setBlockNumber(scanner.nextInt()); if (arrayList.size()<4) { arrayList.add(arrayList1.get(Find(arrayList1, P))); } System.out.println("已修改页表"); printPageTable(); } public void physicsAD(){ for (int i=0;i<arrayList1.size();i++){ if (P==arrayList1.get(i).getPageNumber()){ int address=arrayList1.get(i).getBlockNumber()*(int) Math.pow(2,10)+d; System.out.println("物理地址为"+address); System.out.println("地址变换结束"); } } } }
AT.java
package OperatingSystem.experiment2.AddressTransformation; import java.util.Scanner; public class AT { public static void main(String[] args) { Scanner scanner=new Scanner(System.in); System.out.println("请输入页表的外存地址,假设页面的大小为1KB"); Conversion conversion=new Conversion(); System.out.println("1.输入逻辑地址"); System.out.println("2.退出程序"); boolean flag=true; while (flag) { System.out.println("请输入您的选择:"); switch (scanner.next()) { case "1": System.out.println("请输入逻辑地址:"); try { conversion.exchange(scanner.nextInt()); conversion.Retrieval(); }catch (CrossedException e){ System.out.println(e.getMessage()); } break; case "2": System.out.println("退出程序"); flag=false; break; default: System.out.println("操作错误,请重新选择"); } } } }