页面置换算法实验报告.docx
《页面置换算法实验报告.docx》由会员分享,可在线阅读,更多相关《页面置换算法实验报告.docx(52页珍藏版)》请在冰豆网上搜索。
页面置换算法实验报告
页面置换算法
实验报告
一、实验目得:
设计与实现最佳置换算法、随机置换算法、先进先出置换算法、最近最久未使用置换算法、简单Clock置换算法及改进型Clock置换算法;通过支持页面访问序列随机发生实现有关算法得测试及性能比较、
2、实验内容:
●虚拟内存页面总数为N,页号从0到N—1
●物理内存由M个物理块组成
●页面访问序列串就是一个整数序列,整数得取值范围为0到N-1、页面访问序列串中得每个元素p表示对页面p得一次访问
●页表用整数数组或结构数组来表示
❑符合局部访问特性得随机生成算法
1.确定虚拟内存得尺寸N,工作集得起始位置p,工作集中包含得页数e,工作集移动率m(每处理m个页面访问则将起始位置p+1),以及一个范围在0与1之间得值t;
2.生成m个取值范围在p与p +e间得随机数,并记录到页面访问序列串中;
3.生成一个随机数r,0≤ r≤ 1;
4.如果r 〈t,则为p生成一个新值,否则p=(p +1)modN;
5.如果想继续加大页面访问序列串得长度,请返回第2步,否则结束。
3、实验环境:
操作系统:
Windows 7
软件:
VC++6.0
4、实验设计:
本实验包含六种算法,基本内容相差不太,在实现方面并没有用统一得数据结构实现,而就是根据不同算法得特点用不同得数据结构来实现:
1、最佳置换与随机置换所需操作不多,用整数数组模拟内存实现;
2、先进先出置换与最近最久未使用置换具有队列得特性,故用队列模拟内存来实现;
3、CLOCK置换与改进得CLOCK置换具有循环队列得特性,故用循环队列模拟内存实现;
4、所有算法都就是采用整数数组来模拟页面访问序列。
5、数据结构设计:
//页面访问序列数组:
intref[ref_size];
//内存数组:
intphy[phy_size];
//队列数据结构定义:
typedefstructQNodeﻩ//定义队列数据结构
{
ﻩintdata;
struct QNode*next;
}QNode,*QueuePtr;
typedef struct
{
QueuePtrfront;ﻩ//头指针
ﻩQueuePtrrear;ﻩ//尾指针
}LinkQueue;
//定义链表数据结构
typedefstructLNode//定义循环链表数据结构
{
intdata;
intflag;ﻩ//访问位
intmodify;ﻩﻩ//修改位
ﻩstruct LNode*next;
}LNode,*LinkList;
6、主要函数说明:
1、voidset_rand_num()ﻩ//产生具有局部特性得随机数列;
2、int Exchange_LNode(LinkList&L,inte,int i)//将链表L中序号为i得结点替换为内容为e得结点;
3、boolSearch_LinkList(LinkList &L,inte,int&i)//找到链表L中内容为e得结点,并用i返回其位置,i=1表示第一个非头结点,依次类推;
4、voidSearch_LL_Flag(LinkList&L,int&i)//用i返回第一个flag为0得结点得位置,i=1表示第一个非头结点,以此类推;
5、voidSet_LL_Flag(LinkList &L,inti)//设置链表L中得序号为i得结点得flag标志为1;
6、int Search_LL_ModifyClock(LinkList&L,int &modify_num)//找到改进得CLOCK算法所需要淘汰得页,用modify_num返回其位置;
此函数根据书上给得思路,第一遍扫描A=0且M=0得页面予以淘汰,若失败,则进行第二轮扫描A=0且M=1得页面,第二轮扫描时将所有访问过得页面得访问位A置0;若失败则重复上述两部;
7、voidSet_LL_modify(LinkList &L,int i)//设置链表L中得序号为i得结点得modify标志为1;
8、boolSearchQueue(LinkQueue&Q,inte,int&i)ﻩ//寻找队列Q中结点data域等于e得结点,并用i返回其在Q中得位置;
9、intgetnum(int a,int b)ﻩﻩ//用b返回元素a在被引用数列中得下一个位置
10、void ORA()//实现最佳置换算法,包括判断页面就是否在内存中、页面进内存、输出内存状态等内容;
11、voidRAND()ﻩ//随机置换算法
12、voidFIFO()ﻩﻩﻩ//先进先出算法
13、voidLRU()ﻩﻩ//最近最久未使用算法
实现最近最久未使用算法得思想就是:
判断待进入内存得页面,如果与内存中得第一个页面相同,则将它移到最后一个,即标志为最近使用得页;如果与内存中得第二个页面相同,则将它删除,并在队列尾部添加相同元素,即标志为最近使用得页;
ﻩ14、voidCLOCK()ﻩﻩ//实现CLOCK算法
15、voidModified_Clock()//实现改进得CLOCK算法
16、intmain()//主函数,调用实现各算法得6个主要函数,并输出各算法得缺页率。
7、实验问题回答:
1、FIFO算法就是否比随机置换算法优越?
答:
FIFO算法比随机置换算法优越,但优势并不明显、
2、LRU算法比FIFO算法优越多少?
答:
LRU算法FIFO算法得效率要高5%—10%,有理论知识可知,页面访问序列具有局部性,而FIFO算法并不符合实际情况。
3、LRU算法与Optimal算法有何差距?
答:
LRU算法就是所有算法中效率最接近Optimal算法得算法,由理论知识可知,Optimal算法就是理想得算法,现实中几乎不可能实现,只能作为一种测评标准,LRU算法就是效率较高得可实现置换算法,但其硬件要求较高,如果规模较小,则略显麻烦。
4、Clock算法与LRU算法有何差距?
答:
Clock算法与LRU算法从结果瞧来差距不大,Clock算法就是使用软件得方式实现LRU算法中硬件得功能,从而在执行效率上会稍逊色些。
8、实验过程结果截图:
实验结果截图
测评一:
测评二:
测评三:
实验过程截图
(注:
只截取第三次测评,蓝色字体表示产生缺页中断)
9、实验结果分析:
1、最佳置换算法效果最佳
不论在那组数据中,最佳置换算法得效果都就是最好得,且都会比其它算法得性能高出不少。
但通过课堂上得学习,我们知道这只就是一种理想化算法,但实际上却难于实现,故主要用于算法评价参照。
2、随机算法得性能总就是最不好得
ﻩ这就是由于随机算法每次总就是从所有页面中随机挑一个置换出去,但我们知道页面得访问存在着局部性得原理,并不就是随机得,因此它得性能较差。
3、最近最久未使用算法得性能较好
相较于先进先出与两种clock算法,最近最久未使用算法得性能略好,我们测试得数据规模相对较小,相信如果采用更大规模得数据,其优势会更加明显。
当从课堂上我们知道要想在实际得应用中实现本算法,用软件得方法速度太慢,影响程序执行效率,如果采用硬件方法实现,则需要增加大量得硬件设备。
4、先进先出与clock算法得性能基本相同
这就是由于两种clock算法遍历链表采用得就就是FIFO得方法,而改进得clock算法相比于简单clock算法得优势主要体现在会根据就是否被修改进行选择,以减少写回所花费得时间。
10、实验总结:
这次实验总体难度不就是很大,需要实现得算法数目虽然不少,但基本思路较为相似,因此实现起来也并不就是十分困难。
通过完成这次实验,除了加深了我对几种策略得理解,锻炼了我得编程能力,另一个巨大得收获就就是了解了一些生成测试数据得方法。
为了使我们得测试数据更贴近现实,我们引入了工作集得概念,并根据实际使用情况得特点设计出尽可能符合实际情况得随机数生成方案。
通过阅读课件再加上自己得理解,我了解了老师得设计思路,感觉这个思路极其巧妙,设计中用到得方法与体现出得很多思想值得我们学习。
11、程序清单:
#include
#include
#include〈time.h〉
#includeh〉
#include
usingnamespace std;
#defineref_size20
#definephy_size3
intref[ref_size];
floatinterrupt[6]={0。
0};
//intref[ref_size]={0};
intphy[phy_size];
//////////////////////////////////////////////////////////////////
void set_rand_num()ﻩ//产生具有局部特性得随机数列
{
cout〈<"页面访问序列:
”<〈endl;
ﻩintp=12;
ﻩint e=4;
intm=4;
inti=0;
ﻩint j=0;
intn=0;
ﻩdoublet=0、6;
inttemp;
ﻩfor(i=0;i<m;i++,j++)
ﻩ{
ﻩﻩSleep(1000*i);
ﻩsrand(time(NULL));
ﻩtemp=rand()%e+p;
ﻩref[j]=temp;
ﻩﻩcout<<ref[j]〈<" ";
}
for(n=0;n〈4;n++)
{
ﻩSleep(1000*n);
srand(time(NULL));
ﻩdoubler=(double)(rand()%10)/10.0;
ﻩ//cout〈ﻩif(r〈t)p=p+int(10*r);
ﻩelse
ﻩp=(p+1)%20;
ﻩfor(i=0;i<m;i++,j++)
{
ﻩSleep(1000*i);
ﻩsrand(time(NULL));
ﻩﻩtemp=rand()%e+p;
ﻩﻩref[j]=temp;
ﻩﻩcout<<ref[j]<<” ”;
}
}
cout〈}
////////////////////////////////////////////////////////////////
typedef structQNodeﻩ//定义队列数据结构
{
int data;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
QueuePtrfront;ﻩ//头指针
QueuePtrrear;ﻩﻩ//尾指针
}LinkQueue;
//定义链表结点
typedef structLNode//定义循环链表数据结构
{
ﻩintdata;
intflag;ﻩ//访问位
ﻩintmodify;ﻩ//修改位
ﻩstructLNode*next;
}LNode,*LinkList;
//////////////////////////////////////////////////////////////////////////对循环链表得一些操作
intCreatList(LinkList &L)//创建循环带有头结点得链表
{
ﻩL=(LinkList)malloc(sizeof(LNode));
if(!
L)exit(-1);
ﻩL->next=L;
ﻩL-〉flag=0;
return1;
}
intExchange_LNode(LinkList&L,inte,inti)//将链表L中序号为i得结点替换为内容为e得结点
{
ﻩif(L->next==L)exit(-1);
ﻩLinkListp,q;
intj=0;
ﻩp=(LinkList)malloc(sizeof(LNode));
ﻩq=(LinkList)malloc(sizeof(LNode));
ﻩq—>data=e;
p=L;
ﻩfor(j=0;j
ﻩp=p—>next;
q—>next=p->next—〉next;
ﻩp-〉next=q;
ﻩq—〉flag=1;//设置新结点得访问位为1
ﻩq—>modify=0;ﻩ//设置新结点得修改位为0
return 1;
}
int Insert_LNode(LinkList&L,inte)//在循环链表中插入新得结点,从L头结点开始依次向后插入
{
ﻩLinkListp,q;
ﻩp=(LinkList)malloc(sizeof(LNode));
ﻩq=(LinkList)malloc(sizeof(LNode));
q-〉data=e;
ﻩq-〉flag=1;ﻩ//设置新结点得访问位为1
ﻩq->modify=0;//设置新结点得修改位为0
p=L;
while(p—>next!
=L)
ﻩ{
ﻩp=p—>next;
ﻩ}
ﻩp->next=q;
ﻩq->next=L;
ﻩreturn1;
}
bool Search_LinkList(LinkList&L,int e,int&i)//找到链表L中内容为e得结点,并用i返回其位置,i=1表示第一个非头结点,依次类推
{
i=1;
ﻩif(L->next==L)exit(-1);
LinkList p;
ﻩp=(LinkList)malloc(sizeof(LNode));
if(!
p)exit(-1);
ﻩp=L-〉next;ﻩ//p指向链表得第一个结点(非头结点)
while(p!
=L&&p-〉data!
=e)
{
ﻩp=p-〉next;
ﻩﻩi++;
ﻩ}
ﻩif(p==L)ﻩﻩ//没有找到符合要求得结点
returnfalse;
returntrue;
}
voidSearch_LL_Flag(LinkList&L,int&i)//用i返回第一个flag为0得结点得位置,i=1表示第一个非头结点,以此类推
{
ﻩi=1;
ﻩLinkListp;
p=(LinkList)malloc(sizeof(LNode));
if(!
p)exit(-1);
p=L-〉next;
ﻩwhile(p-〉flag!
=0)
{
p-〉flag=0;ﻩ//修改访问标志位为0
p=p-〉next;
ﻩif(p==L)ﻩ//跳过头结点
ﻩﻩp=p—〉next;
ﻩi++;
ﻩﻩif(i==4)ﻩﻩ//跳过头结点
ﻩﻩi=1;
}
ﻩ//return1;
}
voidSet_LL_Flag(LinkList&L,inti)ﻩ//设置链表L中得序号为i得结点得flag标志为1;
{
ﻩLinkListp;
p=(LinkList)malloc(sizeof(LNode));
if(!
p)exit(-1);
ﻩp=L-〉next;
if(i==1)
ﻩp->flag=1;
if(i==2)
ﻩ{
ﻩﻩp=p—>next;
p->flag=1;
ﻩ}
if(i==3)
ﻩ{
ﻩﻩp=p->next;
ﻩp=p—〉next;
ﻩﻩp-〉flag=1;
ﻩ}
}
int Search_LL_ModifyClock(LinkList &L,int&modify_num)//找到改进得CLOCK算法所需要淘汰得页,用modify_num返回其位置
{
ﻩmodify_num=1;
ﻩif(L->next==L)exit(-1);
LinkList p;
ﻩp=(LinkList)malloc(sizeof(LNode));
if(!
p) exit(-1);
p=L—〉next;ﻩﻩ//p指向链表得第一个结点(非头结点)
while(p!
=L)//第一轮扫描A=0并且M=0得结点
ﻩ{
ﻩﻩif(p—>flag==0&& p-〉modify==0)
ﻩbreak;//找到
ﻩp=p—>next;
ﻩﻩmodify_num++;
}
if(p==L)
ﻩ{
ﻩmodify_num=1;
ﻩp=L—〉next;
while(p!
=L)ﻩﻩ//第二轮扫描A=0并且M=1得结点,同时修改访问过得结点得访问位为0
{
ﻩﻩif(p->flag!
=0)
ﻩﻩp—>flag=0;
ﻩelseif(p—>modify==1)
ﻩﻩﻩﻩbreak;
ﻩp=p—>next;
ﻩﻩﻩmodify_num++;
ﻩﻩ}
}
if(p==L)
ﻩ{
modify_num=1;
p=L-〉next;
while(p!
=L)//第三轮扫描A=0并且M=0得结点
ﻩ{
ﻩﻩif(p—>flag==0&&p—〉modify==0)
ﻩﻩﻩbreak;
ﻩﻩﻩp=p-〉next;
ﻩﻩmodify_num++;
ﻩﻩ}
ﻩﻩif(p==L)
ﻩ{
ﻩﻩﻩmodify_num=1;
ﻩp=L->next;
while(p!
=L)//第四轮扫描A=0并且M=1得结点
ﻩﻩ{
ﻩif(p—〉flag!
=0)
ﻩﻩﻩﻩp—>flag=0;
elseif(p—〉modify==1)
ﻩﻩﻩbreak;
ﻩp=p-〉next;
ﻩmodify_num++;
ﻩﻩ}
ﻩﻩ}
}
return1;
}
void Set_LL_modify(LinkList&L,inti)//设置链表L中得序号为i得结点得modify标志为1;
{
LinkList p;
ﻩp=(LinkList)malloc(sizeof(LNode));
if(!
p)exit(-1);
p=L—>next;
if(i==0)
ﻩp-〉modify=1;
if(i==1)
{
ﻩﻩp=p-〉next;
p->modify=1;
}
if(i==2)
{
p=p->next;
ﻩp=p-〉next;
ﻩp->modify=1;
ﻩ}
}
intDestroyLinkList(LinkList&L)ﻩ//删除链表,并释放链表空间
{
ﻩLinkList p,q;
ﻩp=(LinkList)malloc(sizeof(LNode));
ﻩif(!
p)exit(—1);
ﻩq=(LinkList)malloc(sizeof(LNode));
if(!
q)exit(-1);
ﻩp=L—>next;
ﻩwhile(p!
=L)
{
ﻩq=p->next;
ﻩfree(p);
p=q;
ﻩ}
free(q);
return1;
}
////////////////////////////////////////////////////////////////对队列得一些操作
intInitQueue(LinkQueue&Q)//队列初始化
{
Q、front=Q、rear=(QueuePtr)malloc(sizeof(QNode));
if(!
Q、front)exit(—1);
Q.front—>next=NULL;
ﻩreturn1;
}
int EnQueue(LinkQueue &Q,inte)ﻩ//插入元素e为Q得新得队尾元素
{
ﻩQueuePtrp;
ﻩp=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(-1);
p—>data=e;
p->next=NULL;
ﻩQ、rear->next=p;
Q、rear=p;
return 1;
}
intDeQueue(LinkQueue&Q,int&e)ﻩ//若队列不空,则删除Q得队头元素,用e返回其值
{
if(Q。
front==Q.rear) return—1;
QueuePtrp;
ﻩp=(QueuePtr)malloc(sizeof(QNode));
p=Q、front-〉next;
e=p->data;
Q。
front-〉next=p->next;
if(Q.rear==p)
ﻩQ、rear=Q。
front;
ﻩfree(p);
ﻩreturn1;
}
bool SearchQueue(LinkQueue&Q,int e,int &i)//寻找队列Q中结点data域等于e得结点,并用i返回其在Q中得位置
{
ﻩi=1;
if(Q。
front==Q.rear)exit(-1);
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p) exit(-1);
p=Q.front->next;//p指向队列得第一个节点(非头结点)
while(p!
=NULL &&p->data!
=e)
{
ﻩp=p—>next;
i++;
}
if(!
p)
ﻩreturn false;
returntrue;
}
intDelMid_Queue(LinkQueue&Q,int&e)//删除Q得中间元素,并用e返回其值
{
if(Q、front==Q.rear)return-1;
ﻩQueuePtrp;
ﻩp=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(-1);
p=Q.front->next;
ﻩe=p—>next-〉data;
ﻩp->next=p—>next->next;
return1;
}
intDestroyQueue(LinkQueue&Q)ﻩ//删除队列并释放空间
{
while(Q、front)
ﻩ{
Q.rear=Q、front—〉next;
ﻩfree(Q、front);
ﻩﻩQ。
front=Q、rear;
ﻩ}
return1;
}
//////////////////////////////////////////////////////////////
intmax1(inta,intb, intc)ﻩ//返回a,b,c中得最大值
{
ﻩif(a〈b)a=b;
if(a<c)a=c;
return a;
}
int getnum(inta,intb)ﻩﻩ//用b返回元素a在被引用数列中得下一个位置
{
ﻩfor(;b