5.如果想继续加大页面访问序列串的长度,请返回第2步,否则结束。
三、实验环境:
操作系统:
Windows7软件:
VC++
四、实验设计:
本实验包含六种算法,基本内容相差不太,在实现方面并没有用统一的
数据结构实现,而是根据不同算法的特点用不同的数据结构来实现:
1、最佳置换和随机置换所需操作不多,用整数数组模拟内存实现;
2、先进先出置换和最近最久未使用置换具有队列的特性,故用队列模拟内存来实现;
3、CLOCIS换和改进的CLOC置换具有循环队列的特性,故用循环队列模拟内存实现;
4、所有算法都是采用整数数组来模拟页面访问序列。
五、数据结构设计:
//页面访问序列数组:
intref[ref_size];
//内存数组:
intphy[phy_size];
六、主要函数说明:
1、voidset_rand_num()//产生具有局部特性的随机数列;
2、intExchange_LNode(LinkList&L,inte,inti)//将链表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、intSearch_LL_ModifyClock(LinkList&L,int&modify_num)//找到改进的CLOCK算法所需要淘汰的页,用modify_num返回其位置;
此函数根据书上给的思路,第一遍扫描A=0且M=0的页面予以淘汰,若失败,贝U进行第二轮扫描A=0且M=1的页面,第二轮扫描时将所有访问过的页面的访问位A
置0;若失败贝重复上述两部;
7、voidSet_LL_modify(LinkList&L,inti)//设置链表L中的序号为i的结点的
modify标志为1;
8、boolSearchQueue(LinkQueue&Q,inte,int&i)//寻找队列Q中结点data域等
于e的结点,并用i返回其在Q中的位置;
9、intgetnum(inta,intb)//用b返回元素a在被引用数列中的下一个位
置
10、voidORA()//实现最佳置换算法,包括判断页面是否在内存中、页面进内存、输
出内存状态等内容;
//随机置换算法
//先进先出算法
//最近最久未使用算法
11、voidRAND()
12、voidFIFO()
13、voidLRU()
实现最近最久未使用算法的思想是:
判断待进入内存的页面,如果与内存中的第个页面相同,贝将它移到最后一个,即标志为最近使用的页;如果与内存中的第二
个页面相同,贝将它删除,并在队列尾部添加相同元素,即标志为最近使用的页;
15、voidModified_Clock()//实现改进的CLOCK算法
16、intmain()//主函数,调用实现各算法的6个主要函数,并输出各算法的缺
页率。
七、实验问题回答:
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算法中硬件的功能,从而在执行效率上会稍逊色些。
八、实验过程结果截图:
实验结果截图
测评一:
测评二:
测评三:
实验过程截图
(注:
只截取第三次测评,蓝色字体表示产生缺页中断)
九、实验结果分析:
1、最佳置换算法效果最佳不论在那组数据中,最佳置换算法的效果都是最好的,且都会比其它算法的性能高出不少。
但通过课堂上的学习,我们知道这只是一种理想化算法,但实际上却难于实现,故主要用于算法评价参照。
2、随机算法的性能总是最不好的这是由于随机算法每次总是从所有页面中随机挑一个置换出去,但我们知道页面的访问存在着局部性的原理,并不是随机的,因此它的性能较差。
3、最近最久未使用算法的性能较好
相较于先进先出和两种clock算法,最近最久未使用算法的性能略好,我们测试的数据规模相对较小,相信如果采用更大规模的数据,其优势会更加明显。
当从课堂上我们知道要想在实际的应用中实现本算法,用软件的方法速度太慢,影响程序执行效率,如果采用硬件方法实现,则需要增加大量的硬件设备。
4、先进先出与clock算法的性能基本相同
这是由于两种clock算法遍历链表采用的就是FIFO的方法,而改进的clock算法相比于简单clock算法的优势主要体现在会根据是否被修改进行选择,以减少写回所花费的时间。
十、实验总结:
这次实验总体难度不是很大,需要实现的算法数目虽然不少,但基本思路较为相似,因此实现起来也并不是十分困难。
通过完成这次实验,除了加深了我对几种策略的理解,锻炼了我的编程能力,另一个巨大的收获就是了解了一些生成测试数据的方法。
为了使我们的测试数据更贴近现实,我们引入了工作集的概念,并根据实际使用情况的特点设计出尽可能符合实际情况的随机数生成方案。
通过阅读课件再加上自己的理解,我了解了老师的设计思路,感觉这个思路极其巧妙,设计中用到的方法和体现出的很多思想值得我们学习。
十一、程序清单:
#include
#include<>
#include<>
#include<>
#include<>
usingnamespacestd;
#defineref_size20
#definephy_size3
intref[ref_size];
floatinterrupt[6]={};
//intref[ref_size]={0};
intphy[phy_size];
//////////////////////////////////////////////////////////////////
voidset_rand_num()//产生具有局部特性的随机数列{
cout<<"页面访问序列:
"<intp=12;
inte=4;
intm=4;
inti=0;
intj=0;
intn=0;
doublet=;
inttemp;
for(i=0;i{
Sleep(1000*i);srand(time(NULL));temp=rand()%e+p;ref[j]=temp;cout<}for(n=0;n<4;n++)
{
Sleep(1000*n);srand(time(NULL));
doubler=(double)(rand()%10)/;//cout<if(relsep=(p+1)%20;
for(i=0;i{
Sleep(1000*i);srand(time(NULL));temp=rand()%e+p;ref[j]=temp;cout<}
}
cout<}
////////////////////////////////////////////////////////////////typedefstructQNode//定义队列数据结构
{
intdata;
structQNode*next;
}QNode,*QueuePtr;
typedefstruct
{
//头指针
//尾指针
QueuePtrfront;
QueuePtrrear;
}LinkQueue;
//定义链表结点
typedefstructLNode//{
定义循环链表数据结构
{
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;//设置新结点的修改位为0return1;
}
LinkListp,q;p=(LinkList)malloc(sizeof(LNode));q=(LinkList)malloc(sizeof(LNode));q->data=e;
q->flag=1;//设置新结点的访问位为1
q->modify=0;//设置新结点的修改位为0p=L;
while(p->next!
=L)
{
p=p->next;
}
p->next=q;
q->next=L;
return1;
}
boolSearch_LinkList(LinkList&L,inte,int&i)//找到链表L中内容为e的结点,并用i返回其位置,i=1表示第一个非头结点,依次类推
{
i=1;
if(L->next==L)exit(-1);
LinkListp;
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;
}
}
intSearch_LL_ModifyClock(LinkList&L,int&modify_num)//找到改进的CLOC算法所需要淘汰的页,用modify_num返回其位置
modify_num=1;
if(L->next==L)exit(-1);
LinkListp;
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++;
//设置链表L中的序号为i的结点
//删除链表,并释放链表空间
}
}
return1;
}
voidSet_LL_modify(LinkList&L,inti)的modify标志为1;
{
LinkListp;
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)
{
LinkListp,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)//队列初始化
{
==(QueuePtr)malloc(sizeof(QNode));
if(!
exit(-1);
>next=NULL;
return1;
}
intEnQueue(LinkQueue&Q,inte)//插入元素e为Q的新的队尾元素
{
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(-1);
p->data=e;p->next=NULL;
>next=p;
=p;
return1;
}
intDeQueue(LinkQueue&Q,int&e)//若队列不空,则删除Q的队头元素,
用e返回其值
{
if==return-1;
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
p=>next;
e=p->data;
>next=p->next;
if==p)
一J
free(p);
return1;
}
//寻找队列Q中结点data
boolSearchQueue(LinkQueue&Q,inte,int&i)域等于e的结点,并用i返回其在Q中的位置{
i=1;
if==exit(-1);
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(-1);
p=>next;//p指向队列的第一个节点(非头结点)
while(p!
=NULL&&p->data!
=e)
{p=p->next;i++;
}
if(!
p)
returnfalse;
returntrue;
}
intDelMid_Queue(LinkQueue&Q,int&e)//删除Q的中间元素,并用e
返回其值
{
if==return-1;
QueuePtrp;
p=(QueuePtr)malloc(sizeof(QNode));
if(!
p)exit(-1);
p=>next;
e=p->next->data;p->next=p->next->next;
return1;
}
intDestroyQueue(LinkQueue&Q)//删除队列并释放空间
{
while
{
=>next;
free;
一J
}
return1;
}
//////////////////////////////////////////////////////////////
intmax1(inta,intb,intc)//返回a,b,c中的最大值
{
if(a
if(areturna;
}
intgetnum(inta,intb)//用b返回元素a在被引用数列中的下一个位置
{
for(;b{
if(a==ref[b])
break;
}
returnb;
}
voidORA()/////////////最佳置换算法
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUN
D_INTENSITY|FOREGROUND_RED);
<*************************、'
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUN
D_INTENSITY|FOREGROUND_INTENSITY设/置字体颜色为白色
inti,j;
intnum_0,num_1,num_2,num_max;
intinterrupt_num=0;
//num_0=num_1=num_2=0;
for(i=0;iphy[i]=ref[i];
for(i=0;icout<cout<for(j=phy_size;j{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_INTENSITY);
if(!
(ref[j]==phy[0]||ref[j]==phy[1]||ref[j]==phy[2]))//若产生缺页中断,选择最久不会被使用的页被替换
{
num_0=getnum(phy[0],j+1);
num_1=getnum(phy[1],j+1);
num_2=getnum(phy[2],j+1);
num_max=max1(num_0,num_1,num_2);
if(num_0==num_max)
phy[0]=ref[j];
else
if(nu