操作系统 实验课
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<iostream>
#include<string>
#include <time.h>
#include <stdlib.h>
using namespace std;
const int total_instruction=320; /*指令流长*/
const int total_vp=32; /*虚页长*/
const int clear_period=50; /*清0周期*/
typedef struct /*页面结构*/
{
// int pn; //页号 logic number
int pfn; //页面框架号 physical frame number
int counter; //计数器
int time; //时间
}pl_type;
pl_type pl[total_vp]; /*页面线性结构---指令序列需要使用地址*/
typedef struct pfc_struct /*页面控制结构,调度算法的控制结构*/
{
int pn;
int pfn;
struct pfc_struct *next;
}pfc_type;
pfc_type pfc[total_vp], *freepf_head, *busypf_head, *busypf_tail;
int misspage=0, a[total_instruction]; /* a[]为指令序列*/
int page[total_instruction], offset[total_instruction];/*地址信息*/
/*初始化相关数据结构 total_pf表示内存的块数 */
int initialize(int total_pf)
{
misspage=0;
for(int i=0;i<total_vp;i++)
{
pl[i].pfn=-1; /*置页面控制结构中的页号,页面为空*/
pl[i].counter=0; /*页面控制结构中的访问次数为0*/
pl[i].time=-1; /*访问的时间*/
}
for(i=0;i<total_pf-1;i++) /*建立pfc[i-1]和pfc[i]之间的链接*/
{
pfc[i].next=&pfc[i+1];
pfc[i].pfn=i;
}
pfc[total_pf-1].next=NULL;
pfc[total_pf-1].pfn=total_pf-1;
freepf_head=&pfc[0]; /*空页面队列的头指针为pfc[0]*/
return 0;
}
int FIFO(int total_pf) /*先进先出算法total_pf:用户进程的内存页面数*/
{
pfc_type *p; /*中间变量*/
initialize(total_pf); /*初始化相关页面控制用数据结构*/
busypf_head=busypf_tail=NULL; /*忙页面队列头,队列尾链接*/
for(int i=0;i<total_instruction;i++)
{
if(pl[page[i]].pfn==-1) /*页面失效*/
{
misspage+=1; /*失效次数*/
if(!freepf_head) /*无空闲页面*/
{
p=busypf_head->next; //保存忙页面下一个页面
pl[busypf_head->pn].pfn=-1; //把这个页面换出,更新它的数据成员
freepf_head=busypf_head; /*释放忙页面队列的第一个页面*/
freepf_head->next=NULL; /*表明还是缺页*/
busypf_head=p; //更新忙页面的队头指针
}
p=freepf_head->next;
freepf_head->pn=page[i];
pl[page[i]].pfn=freepf_head->pfn;
freepf_head->next=NULL; /*使busy的尾为null*/
if(!busypf_tail)
{
busypf_tail=busypf_head=freepf_head;
}
else
{
//把刚刚换进来的接在busy_tail后面
busypf_tail->next=freepf_head;
busypf_tail=freepf_head;
}
freepf_head=p; //下一个空页面
}
}
printf("FIFO:%6.4f ",1-(float)misspage/320);
return 0;
}
//LRU算法换出的是最近一段时间最久未使用过的页
面
,
//因此需要在页表中给每一页增加一个域,专门用来记录该页面自上次被访问以来所经历的时间T。
//页面每被访问一次,计时清零。要淘汰一个页面时,从内存的现有页面中选出T值最小的一页调出。
int LRU (int total_pf) /*最近最久未使用算法least recently used*/
{
int min,minj,present_time; /*minj为最小值下标*/
initialize(total_pf);
present_time=0;
for(int i=0;i<total_instruction;i++)
{
if(pl[page[i]].pfn==-1)
{
misspage++;
if(!freepf_head)
{
min=32767; /*设置最大值*/
for(int j=0;j<total_vp;j++) /*找出time的最小值*/
{
if(min>pl[j].time&&pl[j].pfn!=-1)
{
min=pl[j].time;
minj=j;
}
}
freepf_head=&pfc[pl[minj].pfn]; //腾出一个页面
pl[minj].pfn=-1;
pl[minj].time=0;
freepf_head->next=NULL;
}
pl[page[i]].pfn=freepf_head->pfn; //有空闲页面,改为有效
pl[page[i]].time=present_time;
freepf_head=freepf_head->next; //减少一个free 页面,下一次无页面
}
else
{
pl[page[i]].time=present_time; //命中则增加该单元的访问次数
present_time++;
}
}
printf("LRU:%6.4f ",1-(float)misspage/320);
return 0;
}
//该算法在需要淘汰某一页时,从那些最近一个时期内未被访问的页中任选一页淘汰。
//只要在页表中增设一个访问位即可实现。当某页被访问时,访问位置1。
//否则,访问位置0。系统周期性的对所有引用位清零。
//当需要淘汰一页时,从那些访问位为零的页中选一页淘汰。
int NUR(int total_pf ) /*最近未使用算法Not Used recently count表示*/
{
int dp=0,cont_flag,old_dp; //这个算法中counter用于访问位
initialize(total_pf);
for(int i=0;i<total_instruction;i++)
{
if (pl[page[i]].pfn==-1)
{
misspage++;
if(!freepf_head)
{
cont_flag=true;
old_dp=dp;
while(cont_flag) //用cont_flag找到一个访问位counter为0的页面
{
if(pl[dp].counter==0&&pl[dp].pfn!=-1)
cont_flag=false;
else //下一个页面
{
dp++;
if(dp==total_vp) //32个页面找完一遍重新开始一个循环
dp=0;
if(dp==old_dp) // dp累积上一次访问到的地方old_dp,然后访问位重新清零
for(int j=0;j<total_vp;j++)
pl[j].counter=0;
}
}
freepf_head=&pfc[pl[dp].pfn];
pl[dp].pfn=-1;
freepf_head->next=NULL;
}
pl[page[i]].pfn=freepf_head->pfn;
freepf_head->pn=page[i];
freepf_head=freepf_head->next;
}
else
pl[page[i]].counter=1;
if(i%clear_period==0)
for(int j=0;j<total_vp;j++)
pl[j].counter=0;
}
printf("NUR:%6.4f ",1-(float)misspage/320);
return 0;
}
int OPT(int total_pf) /*最佳置
换算法*/
{
int max,maxpage,dist[total_vp];
i
nitialize(total_pf);
for(int i=0;i<total_instruction;i++)
{
if(pl[page[i]].pfn==-1)
{
misspage++;
if(!freepf_head)
{
for(int j=0;j<total_vp;j++)
{
if(pl[j].pfn!=-1) //在主存中的页面,即将找出一个被替换出去的
dist[j]=32767;
else
dist[j]=0; //不在主存中的页面
}
for(j=0;j<total_vp;j++)
{
if((pl[j].pfn!=-1)&&(dist[j]==32767))
{
dist[j]=j;
}
}
max=0;
for(j=0;j<total_vp;j++) //找最远距离的,因为在主存中的最后一页即是在虚存中的最后一页
if(max<dist[j])
{
max=dist[j];
maxpage=j;
}
freepf_head=&pfc[pl[maxpage].pfn];
freepf_head->next=NULL;
pl[maxpage].pfn=-1;
}
pl[page[i]].pfn=freepf_head->pfn;
freepf_head=freepf_head->next;
}
}
printf("OPT:%6.4f ",1-(float)misspage/320);
return 0;
}
/*该算法时根据已知的预测未知的,least frequency Used是最不经常使用置换法*/
//该算法在需要淘汰某页时,首先淘汰到当前为止,被访问次数最少的那一页。
//这只要在页表中给每一页增设一个访问计数器即可实现。每当该页被访问时,访问计数器加1,
//而发生一次缺页中断时,则淘汰计数值最小的那一页,并将所有的计数器清零。
int LFU(int total_pf) //这个算法中counter用于计数
{
int min,minpage;
initialize(total_pf);
for(int i=0;i<total_instruction;i++)
{
if(pl[page[i]].pfn==-1) /*页面失效*/
{
misspage++;
if(!freepf_head) /*无空闲页面*/
{
min=32767;
/*获取counter的使用用频率最小的内存*/
for(int j=0;j<total_vp;j++)
{
if(min>pl[j].counter&&pl[j].pfn!=-1)
{
min=pl[j].counter;
minpage=j;
}
}
freepf_head=&pfc[pl[minpage].pfn];
pl[minpage].pfn=-1;
pl[minpage].counter=0;
freepf_head->next=NULL;
}
pl[page[i]].pfn=freepf_head->pfn; //有空闲页面,改为有效
pl[page[i]].counter++;
freepf_head=freepf_head->next; //减少一个free 页面
}
else
{
pl[page[i]].counter=pl[page[i]].counter+1;
}
}
printf("LFU:%6.4f ",1-(float)misspage/320);
return 0;
}
int main( )
{
srand(time(0));
int s=rand( )%319;
for(int i=0;i<total_instruction;i+=4) /*产生指令队列*/
{
if(s<0||s>319) //这不可能出现的情况
{
cout<<"error"<<endl;
exit(0);
}
a[i]=s; /*任选一指令访问点m*/
a[i+1]=a[i]+1; /*顺序执行一条指令*/
a[i+2]=rand()%a[i]; /*执行前地址指令m*/
a[i+3]=a[i+2]+1; /*顺序执行一条指令*/
s=rand()%(318-a[i+2])+a[i+2]+2;
}
for (i=0;i<to
tal_instruction;i++) /*将指令序列变换成页地址流*/
{
page[i]=a[i]/10;
offset[i]=a[i]%10;
}
for(i=4;i<=32;i++) /*用户内存工作区从4个页面到32个
页面*/
{
cout<<i<<" page fames: "<<endl;
FIFO(i);
LRU(i);
LFU(i);
NUR(i);
OPT(i);
cout<<endl;
}
return 0;
}