存储管理实验报告参考模板.docx
《存储管理实验报告参考模板.docx》由会员分享,可在线阅读,更多相关《存储管理实验报告参考模板.docx(27页珍藏版)》请在冰豆网上搜索。
存储管理实验报告参考模板
昆明理工大学信息工程与自动化学院学生实验报告
(2012—2013学年第二学期)
课程名称:
操作系统开课实验室:
年月日
年级、专业、班
学号
姓名
成绩
实验项目名称
存储管理
指导教师
杨云飞
教师评语
教师签名:
年月日
一、实验目的
存储管理的主要功能之一是合理地分配空间。
请求页式管理是一种常用的虚拟存储管理技术。
通过本次实验,要求学生通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解,通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。
二、实验原理及基本技术路线图(方框原理图)
用C或C++语言模拟实现请求式分页管理。
要求实现:
页表的数据结构、分页式内存空间的分配及回收(建议采用位图法)、地址重定位、页面置换算法(从FIFO,LRU,NRU中任选一种)。
intsubareaSize[num]={8,12,16,32,24,16,64,128,40,64};//分区大小
Process*pro=NULL;//保持进程信息
intProcessNum=0;//进程数目
intapplyProcessNum=0;//每次申请进程数目
intmaxApplyNum=0;//最大可申请数目
int*applyIndex=NULL;//申请进程队列
inttotalApplyNum=0;//申请总数
int*assignPointer=NULL;//已分配内存的进程队列
intassignFlag=0;//分配索引,表示已申请队列已分配的进程数
intexeIndex;//执行的进程号
Node*subareaNode=newNode[3];//分区回收时,进程所在分区及其前,后分区信息
LinkListcreateLinkList(intn);//建立空闲分区链
NodefirstFit(LinkList&head,Processpro);//首次适应算法
NodenestFit(LinkList&head,Processpro,Nodeflag);//循环适应算法
NodebestFit(LinkList&head,Processpro);//最佳适应算法
NodeworstFit(LinkList&head,Processpro);//最坏适应算法
Nodeassign(LinkList&head,intorderIndex,intindex,NodeflagNode);//一次分区分配
intassignMemory(LinkList&head);//内存分配
voidinsertNode(LinkList&head,Nodeq,intindex);//插入节点
NodedeleteNode(LinkList&head,intindex);//删除节点
intdisplay(LinkList&head);//打印分区分配情况
intlowAttemper(int*excursionPointer);//低级调度
intfindSubarea(LinkList&head,intindex);//回收内存
intcreatProcess();//创建进程
Process*randomCreatPro(intn);//随机产生进程
下面是各种方法简述:
(1)最优替换算法,即OPT算法。
上面介绍的几种页面替换算法主要是以主存储器中页面调度情况的历史信息为依据的,它假设将来主存储器中的页面调度情况与过去一段时间内主存储器中的页面调度情况是相同的。
显然,这种假设不总是正确的。
最好的算法应该是选择将来最久不被访问的页面作为被替换的页面,这种替换算法的命中率一定是最高的,它就是最优替换算法。
要实现OPT算法,唯一的办法是让程序先执行一遍,记录下实际的页地址流情况。
根据这个页地址流才能找出当前要被替换的页面。
显然,这样做是不现实的。
因此,OPT算法只是一种理想化的算法,然而,它也是一种很有用的算法。
实际上,经常把这种算法用来作为评价其它页面替换算法好坏的标准。
在其它条件相同的情况下,哪一种页面替换算法的命中率与OPT算法最接近,那么,它就是一种比较好的页面替换算法。
(2)先进先出算法,即FIFO算法(First-InFirst-Outalgorithm)。
这种算法选择最先调入主存储器的页面作为被替换的页面。
它的优点是比较容易实现,能够利用主存储器中页面调度情况的历史信息,但是,没有反映程序的局部性。
因为最先调入主存的页面,很可能也是经常要使用的页面。
(3)最久没有使用算法,即LRU算法(LeastRecentlyUsedalgorithm)。
这种算法把近期最久没有被访问过的页面作为被替换的页面。
它把LFU算法中要记录数量上的多"与"少简化成判断"有"与"无",因此,实现起来比较容易。
(4)近期最少使用算法,即LFU算法(LeastFrequentlyUsedalgorithm)。
这种算法选择近期最少访问的页面作为被替换的页面。
显然,这是一种非常合理的算法,因为到目前为止最少使用的页面,很可能也是将来最少访问的页面。
该算法既充分利用了主存中页面调度情况的历史信息,又正确反映了程序的局部性。
但是,这种算法实现起来非常困难,它要为每个页面设置一个很长的计数器,并且要选择一个固定的时钟为每个计数器定时计数。
在选择被替换页面时,要从所有计数器中找出一个计数值最大的计数器。
因此,通常采用如下一种相对比较简单的方法。
(5)最近未使用法缺页中断率=缺页中断次数总的页面引用次数*100%
三、所用仪器、材料(设备名称、型号、规格等)。
计算机一台
四、实验方法、步骤
#include
#include
#include
#include
#include
#defineSize4
#definenum10
typedefintbyte;
typedefstruct{
bytesubareaSize;//分区大小
intstartLoc;//起始地址
intindex;//分区号
}SubareaTable;//分区表
typedefstructnode{//结点
SubareaTablesubarea;//分区
structnode*next;
intstatus;//状态位0(空闲)1(使用)
}*Node,*LinkList;
typedefstruct{
byteprocessSize;
intsubareaIndex;//保存分区号
intstatus;//进程状态,0(新建)1(执行)-1(终止)-2(未绪。
申请但没有分配内存)2(就绪,已分配内存)
}Process;//进程
intsubareaSize[num]={8,12,16,32,24,16,64,128,40,64};//分区大小
Process*pro=NULL;//保持进程信息
intProcessNum=0;//进程数目
intapplyProcessNum=0;//每次申请进程数目
intmaxApplyNum=0;//最大可申请数目
int*applyIndex=NULL;//申请进程队列
inttotalApplyNum=0;//申请总数
int*assignPointer=NULL;//已分配内存的进程队列
intassignFlag=0;//分配索引,表示已申请队列已分配的进程数
intexeIndex;//执行的进程号
Node*subareaNode=newNode[3];//分区回收时,进程所在分区及其前,后分区信息
LinkListcreateLinkList(intn);//建立空闲分区链
NodefirstFit(LinkList&head,Processpro);//首次适应算法
NodenestFit(LinkList&head,Processpro,Nodeflag);//循环适应算法
NodebestFit(LinkList&head,Processpro);//最佳适应算法
NodeworstFit(LinkList&head,Processpro);//最坏适应算法
Nodeassign(LinkList&head,intorderIndex,intindex,NodeflagNode);//一次分区分配
intassignMemory(LinkList&head);//内存分配
voidinsertNode(LinkList&head,Nodeq,intindex);//插入节点
NodedeleteNode(LinkList&head,intindex);//删除节点
intdisplay(LinkList&head);//打印分区分配情况
intlowAttemper(int*excursionPointer);//低级调度
intfindSubarea(LinkList&head,intindex);//回收内存
intcreatProcess();//创建进程
Process*randomCreatPro(intn);//随机产生进程
LinkListcreateLinkList(intn){//建立空闲分区链
cout<<"-------------创建分区--------------"<LinkListhead;
Nodep;
head=(LinkList)malloc(sizeof(node));
if(head==NULL){
cout<<"头结点分配错误"<returnNULL;
}
head->next=NULL;//链表尾巴设置为NULL
LinkListq=head;
intstart=0;
for(inti=1;i<=n;i++){
p=(Node)malloc(sizeof(node));
if(p==NULL){
cout<<"节点分配错误"<returnNULL;
}
p->next=q->next;
q->next=p;
q=p;
p->subarea.index=i;
p->subarea.subareaSize=subareaSize[i-1];//分区表赋值大小
p->subarea.startLoc=start;
p->status=0;
start+=subareaSize[i-1];
}
cout<<"分区创建成功!
!
!
"<returnhead;
}
NodefirstFit(LinkList&head,Processpro){//首次适应算法
Nodep=head->next;//遍历结点,返回结点,从第一个结点开始遍历
if(p==NULL){
cout<<"空闲链表不存在"<returnNULL;
}
else{
do{
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
p=p->next;
}
while(p!
=NULL);
if(p==NULL){//没找到合适的结点
returnhead;
}
returnp;
}
}
NodenestFit(LinkList&head,Processpro,Nodeflag){//循环适应算法
Nodep=flag->next;//遍历结点
while(p!
=NULL){
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
p=p->next;
}
if(p==NULL){//遍历到链表结尾
p=head;//从头开始遍历
while(p!
=flag){//标记结点
p=p->next;
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
break;
}
}
if(p==flag){//正常跳出循环,没有合适的结点可分配
returnhead;
}else{
returnp;//在flag结点前找到一合适的结点分配
}
}else{
returnp;//在flag结点后找到一合适的结点分配
}
}
NodebestFit(LinkList&head,Processpro){//最佳适应算法
Nodep=head->next;//遍历结点,返回结点,从第一个结点开始遍历
Nodeq;//返回最佳空闲结点
intleave;//剩余空间
intcount=0;//计数器
if(p==NULL){
cout<<"空闲链表不存在"<returnNULL;
}else{
do{
if(p->status==0&&p->subarea.subareaSize>=pro.processSize){
count++;
if(count==1){//第一个可以分配的空闲分区
leave=p->subarea.subareaSize-pro.processSize;
q=p;
}elseif(count>1){
if(p->subarea.subareaSize-pro.processSizeleave=p->subarea.subareaSize-pro.processSize;
q=p;
}
}
}
p=p->next;
}while(p!
=NULL);
returnq;
}
}
NodeworstFit(LinkList&head,Processpro){//最坏适应算法
Nodep=head->next;//遍历结点,返回结点,从第一个结点开始遍历
Nodeq;//返回最大空闲结点
intcount=0;//计数器
if(p==NULL){
cout<<"空闲链表不存在"<returnNULL;
}else{//开始遍历
do{
if(p->status==0){
count++;
if(count==1){//第一个空闲区
q=p;
}
else{//非第一个空闲区
if(p->subarea.subareaSize>q->subarea.subareaSize){//当前结点大于前面最大结点
q=p;
}
}
}
p=p->next;
}while(p!
=NULL);
if(q->subarea.subareaSize>=pro.processSize){
returnq;
}else{
cout<<"进程大小大于最大分区,无法分配"<returnhead;
}
}
}
voidinsertNode(LinkList&head,Nodeq,intindex)
{
Nodep;//遍历结点
intj=1;
if(head==NULL){
cout<<"链表为空";
return;
}
p=head->next;
for(;p;p=p->next){
j++;
if(j>=index)
break;
}
q->next=p->next;
p->next=q;//插入完成
j=q->subarea.index;//j保持q的分区号
q=q->next;//开始修改分区号
j=q->subarea.index;
while(q!
=NULL){
q->subarea.index=j+1;
q=q->next;
j++;
}
}
NodedeleteNode(LinkList&head,intindex){
Nodeq;//保存要删掉的节点
Nodep=head;//遍历的节点
intcount=0;
while(p&&countp=p->next;
count++;
}
q=p->next;
p->next=q->next;
returnq;
}
intfindSubarea(LinkList&head,intindex){
Nodep=head->next;//遍历结点
if(p==NULL){
cout<<"空闲链表不存在"<return0;
}else{
intj=1;
for(;p;j++)
{
p=p->next;
if(j>=index-1)break;
}
for(inti=0;i<3;i++){
subareaNode[i]=p;
p=p->next;
}
return1;
}
}
intdisplay(LinkList&head){//打印分区分配情况
cout<<"-------------分区信息--------------"<Nodep;
if(head==NULL){
cout<<"分区未创建,请先创建分区"<return0;
}
else{
p=head->next;
cout.fill('');
while(p!
=NULL){
cout.width(3);
cout<subarea.index<<"分区的大小:
"<subarea.subareaSize<<"KB"
<<"分区开始位置:
"<subarea.startLoc<<"是否空闲:
"<status<p=p->next;
}
return1;
}
}
intdisplayProcess(){
cout<<"-------------进程信息--------------"<if(pro==NULL){
cout<<"进程未创建,请先创建进程"<return0;
}
for(inti=0;i{
cout<
"<processSize<<"进程状况:
"<if(pro->status==0){
cout<<"创建";
}
elseif(pro->status==1){//进程状态
cout<<"执行";
}elseif(pro->status==-1){
cout<<"终止";
}elseif(pro->status==2){
cout<<"就绪";
}elseif(pro->status==-2){
cout<<"未绪";
}
cout<}
pro-=ProcessNum;
return1;
}
intapplyforProcess(){
cout<<"-------------申请进程--------------"<intindex;
if(pro==NULL){
cout<<"进程未创建,请先创建进程"<return0;
}
cout<<"输入申请进程的数目:
";
cin>>applyProcessNum;
while(applyProcessNum>maxApplyNum){//申请数目大于最大可申请数目
cout<<"申请进程数目大于可申请进程数目,不合法"<cout<<"请重新输入申请进程数:
";
cin>>applyProcessNum;
}
displayProcess();
for(inti=0;icout<<"请输入需要申请的进程(创建进程才能申请):
";
cin>>index;
pro+=(index-1);//修改指针
if(pro->status==0){
cout<applyIndex[i+totalApplyNum]=index-1;//保持申请进程的偏移量
pro->status=-2;//改状态
i++;
maxApplyNum--;
}else{
cout<}
pro-=(index-1);//回首址
}
totalApplyNum+=applyProcessNum;
return1;
}
intassignMemory(LinkList&head){//分配内存
intn;
NodeflagNode;
if(applyProcessNum==0||head==NULL){
cout<<"未申请进程或未建分区....."<return0;
}
do{
cout<<"**********内存分配**********"<cout<cout<cout<cout<cout<<"**************************"<cout<<"请选择:
";
cin>>n;
}while(n<1||n>4);
intcount=0;//第一次分配,从头结点开始,其他重上次分配的节点开始
applyIndex+=assignFlag;//从分配资源的进程开始分配
for(int