【实验名称】LRU算法模拟
【实验目的】
1.、通过请求页式存储管理中页面置换算法模拟设计
2、了解虚拟存储技术的技术特点
3、掌握请求页式虚拟管理的页面置换算法。
【实验原理】
最近最久未使用(LRU)的页面置换算法是根据页面调入内存后的使用情况做出决策的。由于无法预测各页面将来的使用情况,只能利用“最近的过去”作为“最近的将来”的近似,因此,LRU置换算法是选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间t。当需要淘汰一个页面时,选择现有也面中t值最大的,即最近最久未使用的页面予以淘汰。
【实验内容】
实验内容:用C++模拟页面置换算法LRU,加深对LRU算法的认识。
代码(详情见代码注释):
#include<iostream>
using namespace std;
//内存块类
class memory
{
public:
void init();
void alter(int a, int b);
int check_full();
int check_old();
int check_exist(int a);
void run();
void refresh();
friend int manage(memory *My_Memory, int ans, int a);
friend void show(memory *My_Memory, int ans);
private:
int page;
int time;
};
//为了多次初始化
void memory::init()
{
page = 0;
time = 0;
}
//修改内存块保存的页和时间
void memory::alter(int a, int b)
{
page = a;
time = b;
}
//检查该块是否已被占用
int memory::check_full()
{
if (page == 0 && time == 0)
{
return 1;
}
else
{
return 0;
}
}
//检查该块的驻留时间
int memory::check_old()
{
return time;
}
//检查该块中是否保存了页a
int memory::check_exist(int a)
{
if (page == a)
{
return 1;
}
else
{
return 0;
}
}
//时间++
void memory::run()
{
if (page != 0)
{
time++;
}
}
//时间置0
void memory::refresh()
{
time = 0;
}
//调度作业
int manage(memory *My_Memory, int ans, int a)
{
//检查内存块是否已经保存了页面a
for (int i = 0; i < ans; i++)
{
if (My_Memory[i].check_exist(a))
{
cout << "不发生中断,页面" << a << "已在内存块" << i << "中" << endl;
My_Memory[i].refresh();
return 1;
}
}
//检查内存块是否有空闲页面
for (int i = 0; i < ans; i++)
{
if (My_Memory[i].check_full())
{
cout << "发生中断," << "内存块" << i << "空闲中,页面" << a << "装入" << endl;
My_Memory[i].alter(a, 0);
return 0;
}
}
//找到驻留时间最大的块,进行替换
int max_time = 0;
int num = -1;
for (int i = 0; i < ans; i++)
{
if (My_Memory[i].check_old()>max_time)
{
max_time = My_Memory[i].check_old();
num = i;
}
}
cout << "发生中断," << "内存块" << num << "中页面" << My_Memory[num].page << "被替换,页面" << a << "装入" << endl;
My_Memory[num].alter(a, 0);
return 0;
}
//显示内存块当前状态
void show(memory *My_Memory, int ans)
{
cout << "...................................." << endl;
cout << "内存块号";
for (int i = 0; i < ans; i++)
{
cout << " |" << i;
}
cout << "\n页面号 ";
for (int i = 0; i < ans; i++)
{
cout << " |" << My_Memory[i].page;
}
cout << "\n驻留时间";
for (int i = 0; i < ans; i++)
{
cout << " |" << My_Memory[i].time;
}
cout << "\n....................................\n" << endl;
}
int main()
{
cout << "***************************" << endl;
cout << "*** 页面置换算法LRU ***" << endl;
cout << "*** 1.设置存储区块数 ***" << endl;
cout << "*** 2.页面调度模拟 ***" << endl;
cout << "*** 3.缺页率统计 ***" << endl;
cout << "*** 4.退出模拟器 ***" << endl;
cout << "***************************" << endl;
int ans, aans = 0, nohit = 0;
memory My_Memory[100];
int flag;
while (true)
{
cout << "\n请选择功能:";
cin >> flag;
if (flag == 1)
{
//设置存储区块数
cout << "请输入存储区块数:";
cin >> ans;
for (int i = 0; i < ans; i++)
{
My_Memory[i].init();
}
nohit = 0;
aans = 0;
}
else if (flag == 2)
{
//页面调度模拟
while (true)
{
for (int i = 0; i < ans; i++)
{
My_Memory[i].run();
}
cout << "请输入要调入的页面(输入0结束):";
int a;
cin >> a;
if (a == 0)
{
break;
}
aans++;
if (!manage(My_Memory, ans, a))
{
nohit++;
}
show(My_Memory, ans);
}
}
else if (flag == 3)
{
//缺页率统计
cout << "*****************" << endl;
cout << "调度作业 " << aans << "次\n中断 " << nohit << "次\n缺页率 " << double(nohit) / aans * 100.00 << "%" << endl;
cout << "*****************" << endl;
}
else if (flag == 4)
{
//退出
cout << "成功退出!\n" << endl;
break;
}
}
return 0;
}
运行演示:
【小结或讨论】
LRU算法其实是比较容易理解的,它的核心思想就是:“由于无法预测各页面将来的使用情况,只能利用‘最近的过去’作为‘最近的将来’的近似”。在内存没有空闲且所要调入的内存块不在内存中的情况下,把最近最久未使用的页面调出内存再把新页面装入。
实验总体来说还是较为顺利的,既然规定要用C++来写,我就把内存块写成了一个类,并给它加上了void init();void alter(int a, int b); int check_full();int check_old();int check_exist(int a); void run();void refresh()等函数,方便调度函数int manage(memory *My_Memory, int ans, int a)的调用。由于page和time是类的私有成员变量还需声明了友元函数。
LRU算法的核心,就在于manage函数,这个判断的顺序就很重要。我们首先要判断的是我们要调入的页面是否已经在内存中,如果不在,我们则要判断内存中是否存在空闲,如果不存在,最后再根据最近最久未使用原则进行内存块的替换。只要这个判断顺序捋清了,整体问题也就不大了。