您的位置:首页 > 其它

实验五 虚拟内存页面置换算法

2015-12-30 16:45 246 查看
一、  需求分析
说明程序设计的任务和目的,明确规定下述内容:
加深对虚拟内存页面置换概念的理解,进一步掌握先进先出FIFO、最佳置换OPI和最近最久未使用LRU页面置换算法的实现方法。

(1)    输入的形式和输入值的范围;
 输入1-3的整数选择算法

 已在程序中预置好页面信息和页面访问顺序

(2)    输出的形式;
 页面置换的过程和置换后内存的状态

(3)    程序所能达到的功能;
 模拟先出FIFO、最佳置换OPI和最近最久未使用LRU页面置换算法

(4)    测试数据,包括正确的输入及其输出结果和含有错误的输入及其输出结果。
 依次输入1 2 3选择相应算法

        输出置换过程

二、  概要设计
说明本程序中用到的所有抽象数据类型的定义、主程序的流程以及各程序模块之间的层次(调用)关系。
 
页面文件对象
classPage
    {
       publicstring id;//页面文件id
       publicstring name;//页面文件名称
       publicint timeInRAM;//页面文件在内存中的
时间
       publicint comeInTime;//页面文件在内存中的
进入内存的时间
       publicintlatestVisitTimeInPast;//页面文件在内存中的最近的访问时间
       publicint timeSpanToVisit;//该页面在将来第一次访问
到现在的时间间隔
       publicint visitCount;   
//页面文件在内存中的访问次数
     }
内存对象
classRAM
    {
        publicint breakCount;//中断次数
        publicint size;//内存可存放页面文件的总个数
        publicint freeSize;//空闲个数
        publicint freePostion;//置换过程中临时留下的空位索引[默认-2,无空位时为-1]
        publicList<Page>
RAMDetail;//内存中页面文件的状态
   }
三、  详细设计
实现程序模块的具体算法。
 publicPage GetPageofLongest()
 publicPage GetPageofRecentUnused(
string[] orders,int currentOrderIndex)
 publicPage GetPageofLastUseInfutrue(string[]
orders ,int currentOrderIndex)
四、  调试分析
(1)    调试过程中遇到的问题以及解决方法,设计与实现的回顾讨论和分析;
开始时对最近最久未使用算法理解不清楚,导致运行结果正确。以后在编写程序前应对算法充分理解在进行编程,防止时间浪费

五、  用户使用说明
程序的使用说明,列出每一步的操作步骤。
运行程序--选择算法--查看结果

六、  测试结果
列出测试结果,包括输入和输出。






using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Lab5
{
//页面文件
class Page
{

public string id;//页面文件id
public string name;//页面文件名称
public int timeInRAM;//页面文件在内存中的 时间
public int comeInTime;//页面文件在内存中的 进入内存的时间
public int latestVisitTimeInPast;//页面文件在内存中的 最近的访问时间
public int timeSpanToVisit;//该页面在将来第一次访问 到现在的时间间隔
public int visitCount; //页面文件在内存中的 访问次数
public Page(string id, string name)
{
this.id = id;
this.name = name;
timeInRAM = 0;
visitCount = 0;
comeInTime = -1;
latestVisitTimeInPast = int.MinValue;
timeSpanToVisit = int.MaxValue;
}
//页面文件进入内存
public void ComeInRAM(int time)
{
comeInTime = time;
latestVisitTimeInPast = comeInTime;
timeInRAM++;
VistInRAM(time);//进入时访问次数增加
}
//页面文件停留在内存中
public void StayInRAM()
{
timeInRAM++;
}
//页面文件被移出内存
public void GoOutRAM()
{
comeInTime = -1;
timeInRAM=0;
visitCount = 0;
}
//在内存中被访问
public void VistInRAM(int time)
{
latestVisitTimeInPast = comeInTime;
visitCount++;
}
public void Print()
{
Console.Write(name ); //Console.Write(name + "[" + id + "]");
}
}
class RAM
{
public int breakCount;//中断次数
public int size;//内存可存放页面文件的总个数
public int freeSize;//空闲个数
public int freePostion;//置换过程中临时留下的空位索引[默认-2,无空位时为-1]
public List<Page> RAMDetail;//内存中页面文件的状态
public RAM(int size)
{
this.size = size;
freeSize = size;
RAMDetail = new List<Page>();
freePostion = -2;
breakCount = 0;
}
public void PrintPageState()
{
if (size != RAMDetail.Count+freeSize)
{
Console.WriteLine("数据有误");
return;
}

for (int i = 0; i < RAMDetail.Count; i++)
{
RAMDetail[i].Print();
}
}
//新进入页面文件
public void ComeIn(Page page,int time)
{
page.ComeInRAM(time);
if( freePostion == -2)
{
RAMDetail.Add(page);
}
else
{
RAMDetail.Insert(freePostion,page);
}
freeSize--;

if(freeSize==0)
{
freePostion = -1;
}
Console.WriteLine("\n---正在将[" + page.name + "]装入内存...\n");
}
//丢弃页面文件
public void GoOut(Page page)
{
page.GoOutRAM();
freePostion = GetIndexById(page.id);//找到位置
RAMDetail.RemoveAt(freePostion);
freeSize++;
Console.WriteLine("\n---正在将[" + page.name + "]移出内存...\n");
}
//不置换页面时调用
public void FinishChage()
{
for (int k = 0; k < RAMDetail.Count; k++)
{
RAMDetail[k].StayInRAM();
}
PrintPageState(); Console.WriteLine("");
}
public bool IsInRAM(Page page)
{
return (from t in RAMDetail
where t.id == page.id
select t).FirstOrDefault() == null ? false : true;
}
//1-【FIFO】先进先出 获取最先进入的(在内存中待的时间最长)
public Page GetPageofLongest()
{
int maxValue = 0;
int maxIndex = 0;
for (int i = 0; i < RAMDetail.Count; i++)
{
if (RAMDetail[i].timeInRAM > maxValue)
{
maxIndex = i;
maxValue = RAMDetail[i].timeInRAM;
}

}
return RAMDetail[maxIndex];
}
//2-【LRU】最近最久 //往当前序列向前看 n-1个,如果内存中的页面文件出现了,则从缓存中移出,若均未出现,则找出最先进入的返回
public Page GetPageofRecentUnused( string[] orders,int currentOrderIndex)
{

//创建缓存
List<Page> temp = new List<Page>(RAMDetail);
//查找历史访问
int start = currentOrderIndex - 1;
int end=start - (size - 1)+1;
for (int i = start; i >= end; i--)
{
//判断该页是否在内存中
int index=GetIndexById(orders[i]);
//如果在内存中
if (index != -1)
{//从缓存中删除
temp.Remove(Tool.GetPageById(RAMDetail, orders[i]));
}
}
//缓存中剩余数量大于1
return temp.Count > 1 ? Tool.GetPageofLongest(temp) : temp[0];
}
//3-【OPT】最佳 根据请求序列找出 最后使用的那个移出
public Page GetPageofLastUseInfutrue(string[] orders ,int currentOrderIndex)
{
//将来再也不会被请求的页面集合
List<Page> dontShowPageList = new List<Page>();

int start = currentOrderIndex + 1;
int end = orders.Length-1;
for (int i = 0; i < RAMDetail.Count;i++ )
{
bool pageWiilUse = false;
Page currentPage=RAMDetail[i];
//该页面在将来第一次访问 到现在的时间间隔
int timeSpanToVisit = 1;
for (int j = start; j < end; j++)
{
//计算间隔
if(currentPage.id==orders[j])
{
currentPage.timeSpanToVisit = timeSpanToVisit;
break;
}
else
{
timeSpanToVisit++;
}
}

//遍历完序列都没找到,加入集合
if (timeSpanToVisit == end-start+1)
dontShowPageList.Add(currentPage);
}

//如果不需要的少于1个
if (dontShowPageList.Count <=1 )
{
//找出最timeSpanToVisit最大的返回
int maxValue =int.MaxValue;
int maxIndex = -1;
for (int i = 0; i < RAMDetail.Count; i++)
{
if (RAMDetail[i].timeSpanToVisit >= maxValue)
{
maxValue = RAMDetail[i].timeSpanToVisit;
maxIndex = i;
}
}
return RAMDetail[maxIndex];
}
else
{//否则在不需要中找到待的最久的
return Tool.GetPageofLongest(dontShowPageList);
}

}
//获取最先进入的(在内存中待的时间最长)
public int GetIndexById(string id)
{
for (int i = 0; i < RAMDetail.Count; i++)
{
if (RAMDetail[i].id == id)
{
return i;
}

}
return -1;
}
public void processPage(List<Page> pageList, string[] orders,string flag="1")
{
Console.Write(" \n运行过程如下: \n");
//计时器
int time = 0;
//按id顺序访问页面
for (int i = 0; i < orders.Length; i++)
{
Console.WriteLine("\n------------------正在请求[" + Tool.GetPageById(pageList, orders[i]).name + "]... \n");
time++;
Page currentPage = Tool.GetPageById(pageList, orders[i]);
//有空位
if (freeSize > 0)
{
//新来的进入
ComeIn(currentPage, time);
//结束置换
FinishChage();
}
else
{//没空位
//如果没在RAM中,置换页面并产生中断
if (!IsInRAM(currentPage))
{
//中断
breakCount++;

switch (flag)
{
case "1":
{
//1先进先出(在内存中待的时间最长的先出去)
GoOut(GetPageofLongest());
}
break;
case "2":
{
//2最近最久未使用
GoOut(GetPageofRecentUnused(orders, i));
}
break;
case "3":
{
//3最优
GoOut(GetPageofLastUseInfutrue(orders, i));
}
break;
default: Console.WriteLine("输入有误,程序即将终止!"); break;
}

//新来的进入
ComeIn(currentPage, time);
//结束置换
FinishChage();
}
else
{//如果在RAM中,不置换,全都待在内存中
currentPage.VistInRAM(time);
FinishChage();
}
}

}
}
}
class Tool
{
public static Page GetPageById(List<Page> pageList,string id)
{
return pageList.Where(m => m.id == id).FirstOrDefault();
}
public static void PrintPageList(List<Page> pageList)
{
Console.Write(" \n页面文件如下: \n");
for (int i = 0; i < pageList.Count; i++)
{
pageList[i].Print(); Console.Write(" ");
}
Console.Write("\n");
}
public static void PrintOrders(string[] orders)
{
Console.Write(" \n页面访问顺序[页面ID]如下: \n");
for (int i = 0; i < orders.Length; i++)
{
Console.Write(orders[i]+" ");
}
Console.Write("\n");
}
public static Page GetPageofLongest(List<Page> pageList)
{
int maxValue = 0;
int maxIndex = 0;
for (int i = 0; i < pageList.Count; i++)
{
if (pageList[i].timeInRAM > maxValue)
{
maxIndex = i;
maxValue = pageList[i].timeInRAM;
}

}
return pageList[maxIndex];
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("----------虚拟内存页面置换算法----------- ");
List<Page> pageList = new List<Page>();
pageList.Add(new Page("0", "页面0"));
pageList.Add(new Page("1","页面1"));
pageList.Add(new Page("2", "页面2"));
pageList.Add(new Page("3", "页面3"));
pageList.Add(new Page("4", "页面4"));
pageList.Add(new Page("5", "页面5"));
pageList.Add(new Page("6", "页面6"));
string[] orders = new string[] { "6", "0", "1", "2", "0", "3", "0", "4", "2", "3" };
Tool.PrintPageList(pageList);
Tool.PrintOrders(orders);
RAM ram = new RAM(3);

Console.Write(" \n选择算法: 1-【FIFO】先进先出 2-【LRU】最近最久 3-【OPT】最佳 \n");

ram.processPage(pageList, orders,Console.ReadLine());
Console.ReadLine();
}
}
}



 

七、  附录
带注释的源程序,注释应清楚具体;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: