存储管理实验
实验五 存储管理
一、实验目的
加深对于存储管理的了解,掌握虚拟存储器的实现原理;观察和了解重要的页面
置换算法和置换过程。练习模拟算法的编程技巧,锻炼分析试验数据的能力。
二、实验内容
请在以上示例实验程序中补充―增强二次机会‖等置换算法的模拟程序。输入不同
的内存页面引用串和实存帧数,观察并分析其页面置换效果和性能,并将其与 LRU
和 FIFO 算法进行比较。改进以上示例实验程序,使之能够随机的产生内存页面引
用串,以便能动态的观测各种置换算法的性能。
三、实验要求
1.
说明您做了哪些不同的引用串在不同实存帧中的测试,发现了哪些现象?
2.
选择一些典型的现象作出不同算法中帧数与缺页数的曲线图。
3.
说明您的程序是怎样模拟―增强二次机会‖等置换算法的?
4.
综合分析实验结果中各种页面置换算法各适应于怎样的页面引用串和和内存
帧数。
5.
根据实验程序、调试过程和结果分析写出实验报告。
四、实验步骤
1)打开一终端命令行窗体,新建一个文件夹,在该文件夹中建立以下名为vmrp.h的C语言程序,该程序皆为头文件,该程序代码为:
#include <iostream>
#include <iomanip>
#include <malloc.h>
class Replace{
public:
Replace();
~Replace();
void InitSpace(char * MethodName); //初始化页号记录
void Report(void); // 报告算法执行情况
void Fifo(void); //先进先出算法
void Lru(void); //最近最旧未用算法
void Clock(void); //时钟(二次机会)置换算法
void Eclock(void); //增强二次机会置换算法
void Lfu(void); //最不经常使用置换算法
void Mfu(void); //最经常使用置换算法
private:
int * ReferencePage ; //存放要访问到的页号
int * EliminatePage ; //存放淘汰页号
int * PageFrames ; //存放当前正在实存中的页号
int PageNumber; //访问页数
int FrameNumber; //实存帧数
int FaultNumber; //失败页数
};
2)新建一个文件夹,在该文件夹中建立以下名为vmrp.cc的C语言程序,该程序皆为头文件,该程序代码为:#include "vmrp.h"
using namespace std;
Replace::Replace(){
int i;
//设定总得访问页数,并分配相应的引用页号和淘汰页号记录数组空间
cout << "Please input page numbers :" ;
cin >> PageNumber;
ReferencePage = new int[sizeof(int) * PageNumber];
EliminatePage = new int[sizeof(int) * PageNumber];
//输入引用页号序列(页面走向),初始化引用页数组
cout << "Please input reference page string :";
for (i = 0; i < PageNumber; i++)
cin >> ReferencePage[i];//引用页暂存引用数组
//设定内存实页数(帧数),并分配相应的实页号记录数组空间(页号栈)
cout << "Please input page frames :";
cin >> FrameNumber;
PageFrames = new int[sizeof(int) * FrameNumber];
}
Replace::~Replace(){}
void Replace::InitSpace(char * MethodName)
{
int i;
cout << endl << MethodName << endl;
FaultNumber=0;
//引用还未开始,-1 表示无引用页
for (i = 0; i < PageNumber; i++)
EliminatePage[i] = -1;
for(i = 0; i < FrameNumber; i++)
PageFrames[i] = -1;
}
//分析统计选择的算法对于当前输入的页面走向的性能
void Replace::Report(void){
//报告淘汰页顺序
cout << endl << "Eliminate page:";
for(int i=0; EliminatePage[i]!=-1; i++) cout << EliminatePage[i] << " ";
//报告缺页数和缺页率
cout << endl << "Number of page faults = " << FaultNumber << endl;
cout << setw(6) << setprecision(3) ;
cout << "Rate of page faults = " << 100*(float)FaultNumber/(float)PageNumber <<"%" <<endl;
}
//最近最旧未用置换算法
void Replace::Lru(void)
{
int i,j,k,l,next;
InitSpace("LRU");
//循环装入引用页
for(k=0,l=0; k < PageNumber; k++){
next=ReferencePage[k];
for (i=0; i<FrameNumber; i++){
if(next == PageFrames[i]){
next= PageFrames[i];
for(j=i;j>0;j--) PageFrames[j] = PageFrames[j-1];
PageFrames[0]=next;
break;
}
}
if(PageFrames[0] == next){
for(j=0; j<FrameNumber; j++)
if(PageFrames[j]>=0) cout << PageFrames[j] << " ";
cout << endl;
continue; //继续装入下一页
}
else
FaultNumber++;
EliminatePage[l] = PageFrames[FrameNumber-1];
for(j=FrameNumber-1;j>0;j--) PageFrames[j]= PageFrames[j-1];
PageFrames[0]=next; //引用页放栈顶
for(j=0; j<FrameNumber; j++)
if(PageFrames[j]>=0) cout << PageFrames[j] << " ";
if(EliminatePage[l]>=0)
cout << "->" << EliminatePage[l++] << endl;
else
cout << endl;
}
Report();
}
//先进先出置换算法
void Replace::Fifo(void){
int i,j,k,l,next;
InitSpace("FIFO");
//循环装入引用页
for(k=0,j=l=0; k < PageNumber; k++){
next=ReferencePage[k];
//如果引用页已在实存中,报告实存页号
for (i=0; i<FrameNumber; i++) if(next==PageFrames[i]) break;
if (i<FrameNumber){
for(i=0; i<FrameNumber; i++) cout << PageFrames[i] << " ";
cout << endl;
continue; }
FaultNumber++;
EliminatePage[l]= PageFrames[j]; //最先入页号记入淘汰页数组
PageFrames[j]=next; //引用页号放最先入页号处
j = (j+1)%FrameNumber; //最先入页号循环下移
//报告当前实存页号和淘汰页号
for(i=0; i<FrameNumber; i++)
if(PageFrames[i]>=0) cout << PageFrames[i] << " ";
if(EliminatePage[l]>=0)
cout << "->" << EliminatePage[l++] << endl;
else
cout << endl; }
Report();}
//未实现的其他页置换算法入口
void Replace::Clock(void){
InitSpace("CLOCK");
int i,j,k,m,next;
int *test;
test=new int[FrameNumber];
for(i=0;i<FrameNumber;i++){
test[i]=0;}//for
for(k=0,j=0,m=0;k<PageNumber;k++){
next=ReferencePage[k];
for(i=0;i<FrameNumber;i++){
if(next==PageFrames[i]) {
test[i]=1;
break;}
}//for
if (i<FrameNumber){
for(i=0; i<FrameNumber; i++) cout << PageFrames[i] << " ";
cout << endl;
continue; }
FaultNumber++;
j=0;
for(i=0;i<FrameNumber;i++){
if(test[i]==0) {
j=i;
break;}
if((k>=FrameNumber)&&test[i]==1)
{test[i]=0;}}
EliminatePage[m]=PageFrames[j];
PageFrames[j]=next;
test[j]=1;
//for(i=0;i<FrameNumber;i++){cout<<test[i]<<" ";} cout<<endl;
for(i=0; i<FrameNumber; i++) {
if(PageFrames[i]>=0) {cout << PageFrames[i] << " ";}}
if(EliminatePage[m]>=0)
{cout << "->" << EliminatePage[m++] << endl;}
else
cout << endl;
}
Report();
}
void Replace::Eclock (void)
{
InitSpace("ECLOCK");
int i,j,k,m,next;
int *test,*used;
int *tmp,*tmpu;tmp=new int[FrameNumber];tmpu=new int[FrameNumber];
test=new int[FrameNumber];used=new int[FrameNumber];
for(i=0;i<FrameNumber;i++){
test[i]=0;used[i]=0;}//for
for(k=0,j=0,m=0;k<PageNumber;k++){
next=ReferencePage[k];
for(i=0;i<FrameNumber;i++){
if(next==PageFrames[i]) {
used[i]=1;
test[i]=1;
break;}
}//for
if (i<FrameNumber){
for(i=0; i<FrameNumber; i++) {cout << PageFrames[i] << " ";used[i]=0;}
cout << endl;
continue; }
FaultNumber++;
j=-1;
for(i=0;i<FrameNumber;i++) {tmp[i]=test[i];tmpu[i]=used[i];}
for(i=0;i<FrameNumber;i++){
if(test[i]==0&&used[i]==0) {
j=i;
//cout<<"0 0"<<endl;
break;}
if((k>=FrameNumber)&&test[i]==1)
{test[i]=0;}
}
if(j==-1){
for(i=0;i<FrameNumber;i++){ test[i]=tmp[i];tmpu[i]=used[i];}
for(i=0;i<FrameNumber;i++){
if(test[i]==0&&used[i]==1) {
j=i;
//cout<<"0 1"<<endl;
break;}
if((k>=FrameNumber)&&test[i]==1)
{test[i]=0;}
}}
if(j==-1){
for(i=0;i<FrameNumber;i++) { test[i]=tmp[i];tmpu[i]=used[i];}
for(i=0;i<FrameNumber;i++){
if(test[i]==1&&used[i]==0) {
j=i;
//cout<<" 1 0"<<endl;
break;}
if((k>=FrameNumber)&&test[i]==1)
{test[i]=0;}
}}
if(j==-1){
//cout<<"1 1"<<endl;
for(i=0;i<FrameNumber;i++) {test[i]=tmp[i];tmpu[i]=used[i];}
if(k>=FrameNumber){
for(i=0;i<=FrameNumber;i++)
{
used[i]=0;
test[i]=0;
}
j=0;
}
else j=k;
}
if(k>=FrameNumber)
for(i=0;i<=FrameNumber;i++)
{if(i!=j) used[i]=0;}
EliminatePage[m]=PageFrames[j];
PageFrames[j]=next;
test[j]=1;
used[j]=1;
for(i=0; i<FrameNumber; i++) {
if(PageFrames[i]>=0) {cout << PageFrames[i] << " "; }}
if(EliminatePage[m]>=0)
{cout << "->" << EliminatePage[m++] ;
for(i=0; i<FrameNumber; i++)
{cout<<" "<<test[i]<<" "<< used[i]; }
cout<< endl;}
else
cout << endl;
}
Report();
}
void Replace::Lfu(void)
{
InitSpace("LFU");
int i,j,k,m,next;
int *times;
times=new int[10];
for(i=0;i<10;i++) times[i]=0;
for(k=0,j=0,m=0;k<PageNumber;k++){
next=ReferencePage[k];
for(i=0;i<FrameNumber;i++){
if(next==PageFrames[i]) {
times[next]++;
break;}}//for
if (i<FrameNumber){
for(i=0; i<FrameNumber; i++) cout << PageFrames[i] << " ";
cout << endl;
continue; }
FaultNumber++;
int mintimes=times[PageFrames[0]];
int indexofmin=0;
for(i=0;i<FrameNumber;i++){
if (k==1) {indexofmin=1; break;}
if (k==2) {indexofmin=2; break;}
if(mintimes>times[PageFrames[i]]) {
mintimes=times[PageFrames[i]];
indexofmin=i;
}}
EliminatePage[m]=PageFrames[indexofmin];
PageFrames[indexofmin]=next;
times[next]++;
for(i=0; i<FrameNumber; i++) {
if(PageFrames[i]>=0) {cout << PageFrames[i] << " ";}}
if(EliminatePage[m]>=0)
{cout << "->" << EliminatePage[m++] << endl;}
else
cout << endl;
}
Report();
}
void Replace::Mfu(void)
{
int i,j,k,m,next;
int *times;
times=new int[10];
for(i=0;i<10;i++) times[i]=0;
InitSpace("MFU");
for(k=0,j=0,m=0;k<PageNumber;k++){
next=ReferencePage[k];
for(i=0;i<FrameNumber;i++){
if(next==PageFrames[i]) {
times[next]++;
break;}}//for
if (i<FrameNumber){
for(i=0; i<FrameNumber; i++) cout << PageFrames[i] << " ";
cout << endl;
continue; }
FaultNumber++;
int mintimes=times[PageFrames[0]];
int indexofmax=0;
for(i=0;i<FrameNumber;i++){
if (k==1) {indexofmax=1; break;}
if (k==2) {indexofmax=2; break;}
if(mintimes<times[PageFrames[i]]) {
mintimes=times[PageFrames[i]];
indexofmax=i;
}}
EliminatePage[m]=PageFrames[indexofmax];
PageFrames[indexofmax]=next;
times[next]++;
for(i=0; i<FrameNumber; i++) {
if(PageFrames[i]>=0) {cout << PageFrames[i] << " ";}}
if(EliminatePage[m]>=0)
{cout << "->" << EliminatePage[m++] << endl;}
else
cout << endl;
}
Report();
}
int main(int argc,char *argv[]){
Replace * vmpr = new Replace();
vmpr->Lru();
vmpr->Fifo();
vmpr->Clock();
vmpr->Lfu();
vmpr->Mfu();
vmpr->Eclock();
return 0;
}
3)新建一个文件夹,在该文件夹中建立以下名为Makefile的C语言程序,该程序皆为头文件,该程序代码为:head = vmrp.h
srcs = vmrp.cc
objs = vmrp.o
opts = -w -g -c
all: vmrp
vmrp: $(objs)
g++ $(objs) -o vmrp
vmrp.o: $(srcs) $(head)
g++ $(opts) $(srcs)
clean:
rm vmrp *.o
4)输入g++ -g -c vmrp.cc vmrp.h出现error报错如下,更改后再次执行步骤四得到第三张图
5)输入vmrp.o -o vmrp生成vmrp执行文件
6)输入./vmrp即可执行
7)按照提示输入数据
五、实验结果
得到实验结果截图如下:
六、实验小结
通过实验加深了我对页面置换算法和过程的理解,也发现了自己在这方面的许多不足,还有很多需要学习与改正。