页面置换算法模拟实验报告材料

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验编号4
名称页面置换算法模拟
实验目的
通过请求页式存储管理中页面置换算法模拟设计,以便:
1、了解虚拟存储技术的特点
2、掌握请求页式存储管理中页面置换算法
实验内容与步骤
设计一个虚拟存储区和内存工作区,并使用FIFO和LRU算法计算访问命中率。

<程序设计>
先用srand()函数和rand()函数定义和产生指令序列,然后将指令序列变换成相应的页地址流,并针对不同的算法计算相应的命中率。

<程序1>
#include <windows.h> //Windows版,随机函数需要,GetCurrentProcessId()需要
//#include <stdlib.h>//Linux版,随机函数srand和rand需要
#include <stdio.h> //printf()需要
#define TRUE 1
#define FALSE 0
#define INV ALID -1
#define NULL 0
#define total_instruction 320 //共320条指令
#define total_vp 32 //虚存页共32页
#define clear_period 50 //访问次数清零周期
typedef struct{//定义页表结构类型〔页面映射表PMT〕
int pn, pfn, counter, time;//页号、页框号(块号)、一个周期内访问该页面的次数、访问时间
}PMT;
PMT pmt[32];
typedef struct pfc_struct{//页面控制结构
int pn, pfn;
struct pfc_struct *next;
}pfc_type;
pfc_type pfc[32];
pfc_type *freepf_head,*busypf_head,*busypf_tail;//空闲页头指针,忙页头指针,忙页尾指针
int NoPageCount; //缺页次数
int a[total_instruction];//指令流数组
int page[total_instruction], offset[total_instruction];//每条指令的页和页内偏移
void initialize( int );
void FIFO( int );//先进先出
void LRU( int );//最近最久未使用
void NRU( int );//最近最不经常使用
/****************************************************************************
main()
*****************************************************************************/ void main(){
int i,s;
//srand(10*getpid());//用进程号作为初始化随机数队列的种子//Linux版
srand(10*GetCurrentProcessId());//用进程号作为初始化随机数的种子//Windows版
s=rand()%320;//在[0,319]的指令地址之间随机选取一起点m
for(i=0;i<total_instruction;i+=4){//产生指令队列
if(s<0||s>319){
printf("when i==%d,error,s==%d\n",i,s);
exit(0);
}
a[i]=s;//任意选一指令访问点m。

〔将随机数作为指令地址m〕
a[i+1]=a[i]+1;//顺序执行下一条指令
a[i+2]=rand()%(s+2);//在[0,m+1]的前地址之间随机选取一地址,记为m'
a[i+3]=a[i+2]+1;//顺序执行一条指令
s = a[i+2] + (int)rand()%(320-a[i+2]);//在[m',319]的指令地址之间随机选取一起点m
if((a[i+2]>318)||(s>319)) printf("a[%d+2,a number which is:%d and s=%d\n",i,a[i+2],s);
}
for(i=0;i<total_instruction;i++){//将指令序列变成页地址流
page[i]=a[i]/10;
offset[i]=a[i]%10;
}
for(i=4;i<=32;i++){//内存块分别为4块、5块、...32块时的命中率
printf("%2d page frames",i);
FIFO(i);//计算用FIFO置换时,有i个内存块时的命中率
LRU(i);//最近最久未使用
NRU(i);//最近最不经常使用
printf("\n");
}
}
/***************************************************************************
initialize()
形参:内存块数
功能:初始化
*****************************************************************************/ void initialize(int total_pf)//初始化相关数据结构,形参total_pf是用户进程的内存页面数{
int i;
NoPageCount=0;//缺页次数,初始化为0
for(i=0;i<total_vp;i++){
pmt[i].pn=i;//填逻辑页号
pmt[i].pfn=INV ALID;//物理页面号为-1
pmt[i].counter=0;//置页面控制结构中的访问次数为0
pmt[i].time=-1; //置页面控制结构中的时间为-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]
}
/*****************************************************************************
FIFO算法
形参:内存块数
输出:命中率
*****************************************************************************/ void FIFO(int total_pf)//形参total_pf是用户进程的内存页面数
{
int i;
pfc_type *p;
initialize(total_pf);//初始化相关数据结构
busypf_head=busypf_tail=NULL;
for(i=0;i<total_instruction;i++){//访问每条指令
if(pmt[page[i]].pfn==INV ALID){//缺页
NoPageCount+=1;//失效(缺页)次数增1
if(freepf_head==NULL){//无空闲页面
p=busypf_head->next;
pmt[busypf_head->pn].pfn=INV ALID;
freepf_head=busypf_head;//释放忙页面队列的第一个页面
freepf_head->next=NULL;
busypf_head=p;
}
p=freepf_head->next;//按FIFO方式调新页面入内存
freepf_head->next=NULL;
freepf_head->pn=page[i];
pmt[page[i]].pfn=freepf_head->pfn;
if(busypf_tail==NULL) busypf_head=busypf_tail=freepf_head;
else{
busypf_tail->next=freepf_head;//free页面减少一个
busypf_tail=freepf_head;
}
freepf_head=p;
}
}
printf(" FIFO: %",1-(float)NoPageCount/320);
}
/****************************************************************************
LRU算法〔最近最久未使用〕
形参:内存块数
输出:命中率
*****************************************************************************/ void LRU(int total_pf)//形参total_pf是给用户进程的内存块数
{
int min,minj,i,j,present_time;
initialize(total_pf);
present_time=0;
for(i=0;i<total_instruction;i++){
if(pmt[page[i]].pfn==INV ALID){//页面失效
NoPageCount++;
if(freepf_head==NULL){//无空闲页面
min=32767;
for(j=0;j<total_vp;j++)//找出time的最小值
if(min>pmt[j].time&&pmt[j].pfn!=INV ALID){
min=pmt[j].time;
minj=j;
}
freepf_head=&pfc[pmt[minj].pfn];//腾出一个单元
pmt[minj].pfn=INV ALID;
pmt[minj].time=-1;
freepf_head->next=NULL;
}
pmt[page[i]].pfn=freepf_head->pfn;//有空闲页面,改为有效
pmt[page[i]].time=present_time;
freepf_head=freepf_head->next;//减少一个free页面
}
else pmt[page[i]].time=present_time;//更新该页面的访问时间〔并非真的时间,而是循环次数,每执行一条指令,时间加1〕
present_time++;//当前时间加1
}
printf(" LRU: %",1-(float)NoPageCount/320);
}
/****************************************************************************
NRU算法〔最近最不经常使用〕
形参:内存块数
输出:命中率
*****************************************************************************/ void NRU(int total_pf)
{
int i,j,dp,cont_flag,old_dp;
initialize(total_pf);
dp=0;
for(i=0;i<total_instruction;i++){
if(pmt[page[i]].pfn==INV ALID){//缺页
NoPageCount++;
if(freepf_head==NULL){ //无空闲页面
cont_flag=TRUE;
old_dp=dp;
while(cont_flag)
if(pmt[dp].counter==0&&pmt[dp].pfn!=INV ALID)
cont_flag=FALSE;
else{
dp++;
if(dp==total_vp)
dp=0;
if(dp==old_dp)
for(j=0;j<total_vp;j++)
pmt[j].counter=0;
}
freepf_head=&pfc[pmt[dp].pfn];
pmt[dp].pfn=INV ALID;
freepf_head->next=NULL;
}
pmt[page[i]].pfn=freepf_head->pfn;
freepf_head=freepf_head->next;
}
else
pmt[page[i]].counter=1;
if(i%clear_period==0)
for(j=0;j<total_vp;j++)
pmt[j].counter=0;
}
printf(" NUR: %",1-(float)NoPageCount/320);
}
实验结果〔写出结果,截图也可〕
总结〔收获,未实现的步骤〕
这次操作系统课程设计,让我们对操作系统有了更深的认识,首先操作系统是一管理电脑硬件与软件资源的程序,同时也是计算机系统内核与基石。

操作系统是一个庞大的管理控制程序,大致包括5个方面的管理功能:进程与处理机管
理、作业管理、存储管理、设备管理、文件管理。

我们这次课程设计的题目是页面置换算法,是属于存储器管理。

在进程运行过程中,假如其访问的页面不在内存而需把它们调入内存,但内存以无空闲空间时,为了保证该进程能正常的运行,系统必须从内存中调出一页程序或数据送磁盘的兑换区中,但应将哪个页面调出,需根据一定的算法来确定。

通常,把选择换成页面的算法称为页面置换算法。

通过本次课程设计,我们对页面置换算法的了解更加的深刻。

主要有以下置换算法:OPT〔最优置换算法〕、FIFO〔先进先出置换算法〕、LRU 〔最近最久未使用算法〕。

每种算法都有各自的优缺点,OPT算法是实际中不能实现的,但是可以利用该算法去评价其它算法;FIFO算法与进程实际运行的规律不相适用,因为在进程中,有些页面经常被访问;LRU算法是根据页面调入内存后的使用情况进展决策的。

在这次课程设计中,遇到了一些困难,例如怎么实现各种算法,如何进展函数调用与对数据的限制操作等,在遇到这些困难的时候,我们会去查阅资料,仔细看书,尝试用不同的方法解决,在各种方法中选择一种最好的方法,有的时候会碰到不知道如何实现的函数,我们会查看MSDN,这次是用的C++语言做的,每一步都是自己独立完成的,这次课程设计我最大的收获是学以致用,通过这次设计我们看到了自己学习的能力,我们相信在以后的学习中,会更加的努力上进。

最后,还非常感谢辛苦的操作系统教师,首先,因为他辛苦的为我们讲解操作系统这门课,让我们对操作系统有了一定的了解,为这次课程设计奠定了良好的根底,其次,还要感谢他认真指导我们的这次课程设计,给了我们这次总体运用自己能力的机会,我们坚信:只要功夫深,铁杵磨成针。

相关文档
最新文档