页面置换算法:
最佳置换算法(OPT)
先进先出算法(FIFO)
最近最少用算法(LRU)
这个实验的程序打印出每个页面置换算法的页面置换变化示意图、缺页中断次数和缺页中断率,从中可以看出各种算法的优缺点。
代码如下:
package virtualStorageManagement;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Scanner;
import java.util.Stack;
public class virtualStorageManagement {
public static void main(String args[]) {
Arithmetic.chooseArithmetic();
}
}
class Arithmetic{
static int changePageCount = 0; //页面中断次数
static int physicalBlocks = 3; //静态变量物理块数
static int PageNum = 8; //静态变量页数
Queue<Integer> queue;
int queueSize;
Queue<Integer> optQueue;
PageTable pageTable = new PageTable(); //初始化页表
BlocksTable blocksTable = new BlocksTable(); //初始化物理块表
boolean firstPrint = true;
public static void chooseArithmetic() {
System.out.println("请选择页面置换算法");
System.out.println("1.OPT页面置换算法");
System.out.println("2.FIFO页面置换算法");
System.out.println("3.LRU页面置换算法");
System.out.println("4.退出");
Scanner in = new Scanner(System.in);
int item = in.nextInt();
while(true) {
Arithmetic test = new Arithmetic();
if(item == 1) {
test.OptArithmetic();
}
else if(item == 2) {
test.FIFOArithmetic();
}
else if(item == 3) {
test.LRUArithmetic();
}
else return;
System.out.println("请选择页面置换算法");
System.out.println("1.OPT页面置换算法");
System.out.println("2.FIFO页面置换算法");
System.out.println("3.LRU页面置换算法");
System.out.println("4.退出");
item = in.nextInt();
}
}
public void input() {
System.out.println("请输入页面访问序列,输入-1结束输入");
Scanner in = new Scanner(System.in);
queue = new LinkedList<Integer>();
int temp = -1;
temp = in.nextInt();
while(temp != -1) {
queue.offer(temp);
temp = in.nextInt();
}
queueSize = queue.size();
}
int findMaxDistance(int []temp) {
int lenth = temp.length;
int max = temp[0];
int maxItem = 0;
for(int i = 1;i < lenth;i++) {
if(max < temp[i])
{
maxItem = i;
max = temp[i];
}
}
return maxItem;
}
public void changePageOpt(Queue<Integer> tempQueue,int needEnterPage) {
//新建一个数组存储每个物理块当前页面距离下次用到的距离
int[] distanceRecord = new int[Arithmetic.physicalBlocks];
//建立一个关于当前物理块的迭代器
Iterator<physicalBlocks> it = blocksTable.BlockQueue.iterator();
//记录当前迭代器迭代到哪个物理块
int countRecord = 0;
//用循环确定每个物理块的距离
while (it.hasNext()) {//外层循环遍历物理块
physicalBlocks pTemp = it.next();
Iterator<Integer> numIterator = tempQueue.iterator();
//记录距离
int countdistance = 1;
//内层循环遍历所有的输入序列
while(numIterator.hasNext()) {
countdistance++;
int tempPage = numIterator.next();
if(pTemp.usePage == tempPage) {
break;
}
}
distanceRecord[countRecord] = countdistance;
countRecord++;
}
int maxItem = findMaxDistance(distanceRecord);
//获取需要移除的页面的页号
int oldRemovePage = blocksTable.getBlocksByNum(maxItem).usePage;
//把移出主存的页面置为false
pageTable.changePageState(oldRemovePage, false);
//把要装入主存的页号传给物理块
blocksTable.getBlocksByNum(maxItem).usePage = needEnterPage;
//把移入主存的页面置为true
pageTable.changePageState( needEnterPage, true);
blocksTable.hasChange = true;
changePageCount++;
}
public void OptArithmetic() {
changePageCount = 0;
input();
//获得一个输入序列的复制序列
System.out.println("\tOPT页面置换算法");
Queue<Integer> tempQueue = new LinkedList<Integer>(queue);
while(!tempQueue.isEmpty()) {
int tempPageNum = tempQueue.poll();
//判断是否有空的物理块
if(!blocksTable.haveFullBlocks()) {
//判断该页面是否在内存里
if(!pageTable.isInMeomory(tempPageNum)) {
//不在则调用更换页面算法将距离最长的页面置换出去
changePageOpt(new LinkedList<Integer>(tempQueue),tempPageNum);
}
//如果当前页面在物理块中则什么也不做
}else { //如果有空的物理块
physicalBlocks tempBlocks = blocksTable.returnAFullBlock();
tempBlocks.use = true;
tempBlocks.usePage = tempPageNum;
blocksTable.hasChange = true;
pageTable.changePageState( tempPageNum, true);
changePageCount++;
}
showPhysicalBlocksSituation(tempPageNum,1);
if(blocksTable.hasChange == true) {
System.out.println("+");
blocksTable.hasChange = false;
}
else {
System.out.println("");
}
}
System.out.println("\t<+表示产生一次缺页中断>");
System.out.println("该算法一共发生了 " + changePageCount + " 次页面置换,缺页中断率为 " + changePageCount*100/queue.size()+ "%\n" );
}
//FIFO置换算法
public void FIFOArithmetic() {
changePageCount = 0;
input();
//获得一个输入序列的复制序列
Queue<Integer> tempQueue = new LinkedList<Integer>(queue);
int tempQueueSize = tempQueue.size();
System.out.println("\tFIFO页面置换算法");
while(!tempQueue.isEmpty()) {
int tempPageNum = tempQueue.poll();
//判断是否有空的物理块
if(!blocksTable.haveFullBlocks()) {
//判断该页面是否在内存里
if(!pageTable.isInMeomory(tempPageNum)) {
//不在则调用更换页面算法将距离最长的页面置换出去
changePageFIFO(new LinkedList<Integer>(tempQueue),tempPageNum);
}
else {
}
}else { //如果有空的物理块
physicalBlocks tempBlocks = blocksTable.returnAFullBlock();
tempBlocks.use = true;
tempBlocks.usePage = tempPageNum;
blocksTable.hasChange = true;
pageTable.changePageState( tempPageNum, true);
changePageCount++;
}
showPhysicalBlocksSituation(tempPageNum,2);
if(blocksTable.hasChange == true) {
System.out.println("+");
blocksTable.hasChange = false;
}
else {
System.out.println("");
}
}
System.out.println("\t<+表示产生一次缺页中断>");
System.out.println("该算法一共发生了 " + changePageCount + " 次页面置换,缺页中断率为 " + changePageCount*100/tempQueueSize+ "%\n" );
}
public void changeUsePageToLast(int usePage) {
Iterator<physicalBlocks> it = blocksTable.BlockQueue.iterator();
Queue<physicalBlocks> tempBlockQueue = new LinkedList<physicalBlocks>();
physicalBlocks tempBlock;
physicalBlocks lastBlock = null;
while(it.hasNext()) {
tempBlock = it.next();
if(tempBlock.usePage == usePage) {
lastBlock = tempBlock;
}
else {
tempBlockQueue.offer(tempBlock);
}
}
tempBlockQueue.offer(lastBlock);
blocksTable.BlockQueue.poll();
blocksTable.BlockQueue = tempBlockQueue;
}
public void changePageFIFO(Queue<Integer> tempQueue,int needEnterPage) {
//建立一个关于当前物理块的迭代器
Iterator<physicalBlocks> it = blocksTable.BlockQueue.iterator();
int oldPageNum;
physicalBlocks firstBlock = it.next();
firstBlock.blockNum = physicalBlocks - 1;
oldPageNum = firstBlock.usePage;
firstBlock.usePage = needEnterPage;
while (it.hasNext()) {//循环遍历物理块将物理块块号减一
physicalBlocks pTemp = it.next();
pTemp.blockNum -= 1;
}
blocksTable.BlockQueue.poll();
blocksTable.BlockQueue.offer(firstBlock);
//把移出主存的页面置为false
pageTable.changePageState(oldPageNum, false);
//把移入主存的页面置为true
pageTable.changePageState( needEnterPage, true);
blocksTable.hasChange = true;
changePageCount++;
}
//LRU算法
public void LRUArithmetic() {
changePageCount = 0;
input();
System.out.println("\tLRU页面置换算法");
//获得一个输入序列的复制序列
Queue<Integer> tempQueue = new LinkedList<Integer>(queue);
while(!tempQueue.isEmpty()) {
int tempPageNum = tempQueue.poll();
//判断是否有空的物理块
if(!blocksTable.haveFullBlocks()) {
//判断该页面是否在内存里
if(!pageTable.isInMeomory(tempPageNum)) {
//不在则调用更换页面算法将距离最长的页面置换出去
changePageLRU(new LinkedList<Integer>(tempQueue),tempPageNum);
}
else {
changeUsePageToLast(tempPageNum);
}
}else { //如果有空的物理块
physicalBlocks tempBlocks = blocksTable.returnAFullBlock();
tempBlocks.use = true;
tempBlocks.usePage = tempPageNum;
blocksTable.hasChange = true;
pageTable.changePageState( tempPageNum, true);
changePageCount++;
}
showPhysicalBlocksSituation(tempPageNum,3);
if(blocksTable.hasChange == true) {
System.out.println("+");
blocksTable.hasChange = false;
}
else {
System.out.println("");
}
}
System.out.println("\t<+表示产生一次缺页中断>");
System.out.println("该算法一共发生了 " + changePageCount + " 次页面置换,缺页中断率为 " + changePageCount*100/queue.size()+ "%\n" );
}
public void changePageLRU(Queue<Integer> tempQueue,int needEnterPage) {
//建立一个关于当前物理块的迭代器
Iterator<physicalBlocks> it = blocksTable.BlockQueue.iterator();
int oldPageNum;
physicalBlocks firstBlock = it.next();
firstBlock.blockNum = physicalBlocks - 1;
oldPageNum = firstBlock.usePage;
firstBlock.usePage = needEnterPage;
while (it.hasNext()) {//循环遍历物理块将物理块块号减一
physicalBlocks pTemp = it.next();
pTemp.blockNum -= 1;
}
blocksTable.BlockQueue.poll();
blocksTable.BlockQueue.offer(firstBlock);
//把移出主存的页面置为false
pageTable.changePageState(oldPageNum, false);
//把移入主存的页面置为true
pageTable.changePageState( needEnterPage, true);
blocksTable.hasChange = true;
changePageCount++;
}
void showPhysicalBlocksSituation(int enterPage,int printMode) {
Iterator<physicalBlocks> it = blocksTable.BlockQueue.iterator();
if(printMode == 1) {
if(firstPrint == true){
System.out.println("调用页面\t物理块1\t物理块2\t物理块3\t");
firstPrint = false;
}
System.out.print(enterPage + "\t");
while (it.hasNext()) {
physicalBlocks bTemp = it.next();
if(bTemp.use == true) {
System.out.print(bTemp.usePage + "\t");
}
else {
System.out.print("空\t");
}
}
}
else if(printMode == 2 || printMode == 3) {
if(printMode == 2){
if(firstPrint == true){
System.out.println("调用页面\t最新页面\t中间页面\t最旧页面\t");
firstPrint = false;
}
}
else if(printMode == 3) {
if(firstPrint == true){
System.out.println("调用页面\t常用页面\t中间页面\t少用页面\t");
firstPrint = false;
}
}
System.out.print(enterPage + "\t");
Stack<physicalBlocks> stackBlock =new Stack<physicalBlocks>();
int countNull = 0;
while(it.hasNext()) {
physicalBlocks temp = it.next();
if(temp.use == false)
countNull++;
else
stackBlock.push(temp);
}
while (!stackBlock.empty()) {
physicalBlocks bTemp = stackBlock.pop();
System.out.print(bTemp.usePage + "\t");
}
while (countNull-- > 0) {
System.out.print("空\t");
}
}
}
}
//定义物理块
class physicalBlocks{
int blockNum;
boolean use = false;
int usePage = -1;
}
//定义物理块表
class BlocksTable{
Queue<physicalBlocks> BlockQueue;
boolean hasChange = false;
BlocksTable(){
initial();
}
void initial() {
BlockQueue = new LinkedList<physicalBlocks>();
for(int i = 0;i < Arithmetic.physicalBlocks;i++) {
physicalBlocks bTemp = new physicalBlocks();
bTemp.use = false;
bTemp.blockNum = i;
BlockQueue.offer(bTemp);
}
}
boolean haveFullBlocks() {
Iterator<physicalBlocks> it = BlockQueue.iterator();
while (it.hasNext()) {
physicalBlocks bTemp = it.next();
if(bTemp.use == false) {
return true;
}
}
return false;
}
physicalBlocks returnAFullBlock(){
Iterator<physicalBlocks> it = BlockQueue.iterator();
while (it.hasNext()) {
physicalBlocks bTemp = it.next();
if(bTemp.use == false) {
return bTemp;
}
}
return null;
}
Iterator<physicalBlocks> getIterator(){
return BlockQueue.iterator();
}
physicalBlocks getBlocksByNum(int num) {
Iterator<physicalBlocks> it = BlockQueue.iterator();
while (it.hasNext()) {
physicalBlocks bTemp = it.next();
if(bTemp.blockNum == num) {
return bTemp;
}
}
return null;
}
}
//定义每一页
class Page{
int pageNum;
boolean inMemory = false;
}
//定义一个页表
class PageTable{
int PageNum = 8;
Queue<Page> PageQueue;
PageTable(){
initial();
}
void initial() {
PageQueue = new LinkedList<Page>();
for(int i = 0;i < Arithmetic.PageNum;i++) {
Page pTemp = new Page();
pTemp.pageNum = i;
PageQueue.offer(pTemp);
}
}
boolean isInMeomory(int PageNum){
Iterator<Page> it = PageQueue.iterator();
while (it.hasNext()) {
Page pTemp = it.next();
if(pTemp.pageNum == PageNum) {
if(pTemp.inMemory == false) {
return false;
}
else {
return true;
}
}
}
return false;
}
void changePageState(int PageNum,boolean setInMemory) {
Iterator<Page> it = PageQueue.iterator();
while (it.hasNext()) {
Page pTemp = it.next();
if(pTemp.pageNum == PageNum) {
//1代表在页在主存中,0代表页不在主存中
pTemp.inMemory = setInMemory;
break;
}
}
}
}
实验结果如下如下: