动态可变分区存储管理模拟系统.docx
- 文档编号:9093114
- 上传时间:2023-02-03
- 格式:DOCX
- 页数:33
- 大小:521.25KB
动态可变分区存储管理模拟系统.docx
《动态可变分区存储管理模拟系统.docx》由会员分享,可在线阅读,更多相关《动态可变分区存储管理模拟系统.docx(33页珍藏版)》请在冰豆网上搜索。
动态可变分区存储管理模拟系统
青岛农业大学
理学与信息科学学院
操作系统课程设计报告
设计题目仿真实现动态可变分区存储管理模拟系统
—最佳适应算法和最先适应算法
学生专业班级计算机科学与技术2011级03班
学生姓名(学号)张明珠(H20110684)
设计小组其他同学姓名(学号)刘玉婷(H20110661)
宋璇(H20110162)
指导教师牟春莲
完成时间2014.06.15
实习(设计)地点信息楼218
2014年6月16日
一、课程设计目的
操作系统的理论知识只有通过操作系统的实际操作和编程才能真正地理解和掌握,没有实践操作系统的操作和编程,学习操作系统就是纸上谈兵。
操作系统课程设计是在学习完《操作系统》课程后进行的一次全面、综合实习,是计算机科学与技术专业的重要实践性教学环节。
通过课程设计,达到如下目的:
1、巩固和加深对操作系统原理的理解,提高综合运用本课程所学知识的能力。
2、培养学生选用参考书,查阅手册及文献资料的能力;培养独立思考、深入研究、分析问题、解决问题的能力。
3、通过实际操作系统的分析设计、编程调试,掌握系统软件的分析方法和工程设计方法。
4、能够按要求编写课程设计报告书,能正确阐述设计过程和实验结果、正确绘制系统和程序框图。
5、通过课程设计,培养学生严谨的科学态度、严肃认真的工作作风和团队协作精神。
二、设计任务
题目描述:
仿真实现动态可变分区存储管理模拟系统。
内存调度策略可采用最先适应算法、最佳适应法等,并对各种算法进行性能比较。
为了实现分区分配,系统中必须配置相应的数据结构,用来描述空闲区和已分配区的情况,为分配提供依据。
常用的数据结构有两种形式:
空闲分区表和空闲分区链。
为把一个新作业装入内存,须按照一定的算法,从空闲分区表或空闲分区链中选出一个分区分配给该作业.
设计要求:
1.采用指定算法模拟动态分区管理方式的主存分配。
能够处理以下的情形:
⑴随机出现的进程i申请jKB内存,程序能判断是否能分配,如果能分配,要求输出分配的首地址Faddress,并要求输出内存使用情况和空闲情况。
内存情况输出的格式为:
Faddress该分区的首地址;Eaddress该分区的尾地址Len分区长度;Process如果使用,使用的进程号,否则为0。
⑵主存分配函数实现寻找空闲区、空闲区表的修改、已分配区表的修改功能。
成员分工:
张明珠申请内存、查看进程之间的前后的区域状态、释放进程
刘玉婷最先适应算法、将其释放的内存插入空闲块中、初始化
宋璇最佳适应算法、将新项插入已分配表中、退出
张明珠宋璇刘玉婷整个界面的优化、界面设计、总体思路
三、分析与设计
1.设计思路
存储器是计算机的重要组成部分,存储空间是操作系统管理的宝贵资源,虽然其容量在不断扩大,但仍然远远不能满足软件发展的需要。
对存储资源进行有效的管理,不仅关系到存储器的利用率,而且还对操作系统的性能和效率有很大的影响。
操作系统的存储管理的基本功能有:
存储分配、地址转换和存储保护、存储共享、存储扩充。
存储分配指为选中的多道运行的作业分配主存空间;地址转换是把逻辑地址空间中的用户程序通过静态重定位或动态重定位转换和映射到分给的物理地址空间中,以便用户程序的执行;存储保护指各道程序只能访问自己的存储区域,而不能互相干扰,以免其他程序受到有意或无意的破坏;存储共享指主存中的某些程序和数据可供不同用户进程共享。
最简单的单道系统中,一旦一个程序能装入主存,它将一直运行直到结束。
如果程序长度超出了主存的实际容量,可以通过覆盖和交换的技术获得解决。
更多的操作系统支持多个用户进程在主存同时执行,能满足多道程序设计需要的最简单的存储管理技术是分区方式,有分固定分区和可变分区。
可变分区的分配(如图
(1)所示)算法包括:
最先适应、下次适应、最佳适应、最坏适应和快速适应等分配算法。
图
(1)动态内存分配
采用分区方式管理存储器,每道程序总是要求占用主存的一个或几个连续的存储区域,主存中会产生许多碎片。
因此,有时为了接纳一个新的作业而往往要移动已在主存的信息,这不仅不方便,而且开销不小。
现代计算机都有某种虚存硬设备支持,简单也是常用的虚存是请求分页式虚存管理,于是允许把一个进程的页面存放到若干不相邻的主存页框中。
从搜索速度上看,最先适应算法具有最佳性能。
从回收过程来看,最先适应法也是最佳的。
最先适应算法要求可用表或自由链接按起始地址递增的次序排列。
该算法的最大特点是一旦找到大于或等于所要求内存的长度的分区,则搜索结束。
其优点:
(1)、在释放内存分区时,如果有相邻的空白区就进行合并,使其成为一个较大的空白区;
(2)、本算法的实质是尽可能的利用存储器的低地址部分,在高地址部分则保留较多的或较大的空白区,以后如果需要较大的空白区,就容易能够满足。
最佳适应算法:
从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。
为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。
该算法保留大的空闲区,但造成许多小的空闲区。
最佳适应算法将可利用空间表中一个大小不小于“请求”且最接近“请求”的空闲块的一部分分配给用户。
分配与回收都需要对可利用空间表从头至尾查询一遍。
为了避免每次分配都要查询整个链表,通常要求节点从大到小排序,由此只需找到第一个足够大的空闲块即可予以分配。
但回收时,必须把回收的空闲块放置在符合大小顺序关系的链表位置。
在分配时容易产生太小而无法利用的内存碎片,同时这种做法也保留了那些很大的内存块以备响应将来发生的内存量较大的用户“请求”,从而使整个链表逐渐趋向于节点大小差别甚远的状态。
这种分配算法适合请求分配内存大小范围较广的系统,此算法比较费时间。
在进行内存分配时,从空闲分区表(或空闲分区链)首开始顺序查找,直到找到第一个能满足其大小要求的空闲分区为止。
如果该空闲分区大于作业的大小,则从该分区中划出一块内存空间分配给请求者,将剩余空闲区仍然留在空闲分区表(或空闲分区链)中。
最佳适应算法的特点:
按最佳适应算法为作业分配内存,就能把既满足作业要求又与作业大小最接近的空闲分区分配给作业。
保留了大的空闲区,但分割后的剩余空闲区很小。
本课程设计就是分析动态分区法,与固定分区法相比,动态分区法在作业执行前并不建立分区,分区的建立是在作业的处理过程中进行的。
且其大小可随作业或进程对内存的要求而改变分区的建立是在作业的处理过程中进行的。
且其大小可随作业或进程对内存的要求而改变。
这就改变了固定分区法中那种即使是小作业也要占据大分区的浪费现象,从而提高了内存的利用率。
2.概要设计
动态分区分配是根据进程的实际需要,动态地为之分配内存空间。
在实现可变分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配和回收操作这样三个问题。
为了实现分区分配,系统中必须配置相应的数据结构,用来描述空闲区和已分配区的情况,为分配提供依据。
常用的数据结构有两种形式:
空闲分区表和空闲分区链。
为把一个新作业装入内存,须按照一定的算法,从空闲分区表或空闲分区链中选出一个分区分配给该作业。
目前常用的分配算法有:
首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法和快速适应算法。
在动态分区存储管理方式中,主要操作是分配内存和回收.
系统模块划分:
图
(2)各模块划分图
主流程图:
图(3)主流程图
各程序模块的调用层次:
图(4)各程序调用图
3.详细设计、
数据结构
结构体定义进程
structarea{
intstart;
intend;
intlen;
intsign;
structarea*next;
};
5个数据成员,分别为:
start(分区的首地址)、end、(分区尾地址)len(分区的长度)、sign(标志进程状态)、next(指针用来指向下一个进程)。
内存分配表的图类似与图(5)所示:
区号
分区长度
起始地址
1
18K
40K
5
25K
80K
7
9K
100K
9
6K
120K
图(5)内存分配图
最先适应算法流程如下图所示
请求SIZE大小的分区:
否
否
是
图(6)最先适应算法流程图
最佳适应算法流程如下图所示:
否
是
是否
图(7)最佳适应算法流程图
4、系统实施
在模拟过程中,没有充分理解操作系统教程上关于动态分区法、最先适应法、最优适应法的概念,造成了对设计的目的设计不清楚,不能很好地表达出此设计的功能
寻找空白区方法的不同:
分区分配是对可用表(或自由链)数据结构进行操作,空闲区表可以按空闲区大小的升序(降序)和空闲区首址升序(降序)两种方法进行组织。
才开始并没有理解这两种分配方式对这最佳适应算法和最先适应算法的影响,导致混淆,出现了错误。
对题目理解有误,对模块之间的关系设计不是很清晰。
图(8)初始化图
图(9)申请内存图
图(10)查看已分配区图
图(11)查看空闲区图
图(12)释放内存图
图(13)查看内存状态图
最佳算法和最先算法的比较:
图(13)两算法的对比图
五、程序清单
#include
usingnamespacestd;
#include
structarea{
intstart;定义分区的首地址
intend;定义分区的尾地址
intlen;定义分区的长度
intsign;定义分区的进程号
structarea*next;定义进程的指针
};
structarea*freehead=NULL;声明freehead是型结构指针。
初始freehead指针为空。
structarea*usedhead=NULL;声明usedhead是型结构指针。
初始usedhead指针为空。
voidcreate();创建内存区
voidprint(area*);
voidask(area*);
voidask1(area*);
voidcorrect(area*,int);
area*delempty();初始化
voidinserused(area*,int,int);
voidinserfree(area*);
voidsetfree();
voidlistID();//最先适应法
voidlistlen();/最优适应法
voidswap(area*,area*);
//初始化
area*delempty(){
area*p1=freehead;把空闲区首地址赋值给p1
if(p1->len==0){
if(p1->next==NULL)
returnNULL;
else{
p1=p1->next;指向下一个地址
}
}
}
//最优适应法
voidlistlen(){
intn=0;初始为零
area*p9=freehead->next,*p0=freehead,*p11,*p12,*p13;
while(p0!
=NULL){不为空
p0=p0->next;指向下一个地址
n++;n加一
}
p0=freehead;把空闲区赋值给p0
if(n==1)
return;
else
while(p9!
=NULL){
p12=p0;把p0空闲区给p12
p13=p9;把p9空闲区给p13
p0=p0->next;p0指向下一个地址
p9=p9->next;
while(p13!
=NULL)//把空闲区按从小到大的顺序排列
{
if((p12->len)>(p13->len)){如果p12长度>p13长度
p11=newarea;//把p13给p11
p11->end=p13->end;
p11->len=p13->len;
p11->sign=p13->sign;
p11->start=p13->start;
p11->next=NULL;
swap(p13,p12);交换两个P13,P12
swap(p12,p11);交换两个P12,P11
}
p13=p13->next;
}
}
}
voidswap(area*p13,area*p14)
{
p13->len=p14->len;
p13->sign=p14->sign;
p13->end=p14->end;
p13->start=p14->start;
}
//最先适应法
voidlistID(){
intn=0;
area*p9=freehead->next,*p0=freehead,*p11,*p12,*p13;
while(p0!
=NULL){
p0=p0->next;
n++;
}
p0=freehead;
if(n==1)
return;
else
while(p9!
=NULL){
p12=p0;
p13=p9;
p0=p0->next;
p9=p9->next;
while(p13!
=NULL)//把地址按递增顺序排列
{
if((p12->start)>(p13->start)){
p11=newarea;
p11->end=p13->end;
p11->len=p13->len;
p11->sign=p13->sign;
p11->start=p13->start;
p11->next=NULL;
swap(p13,p12);
swap(p12,p11);
}
p13=p13->next;
}
}
}
voidinserfree(area*p3){查看进程之间的前后的区域状态
intflag=0;
area*pf=freehead,*pe=freehead,*pe1;
while(pf!
=NULL){
if(pf->end!
=p3->start)//判断是否有前继空闲块
pf=pf->next;
elsebreak;
}
if(pf!
=NULL){
flag=5;
}//flag=5有前置空闲块
elseflag=1;//没有置1
while(pe!
=NULL)//判断是否有后继空闲块
{
if(pe->start!
=p3->end)
{
pe1=pe;
pe=pe->next;
}
elsebreak;
}
if(pe!
=NULL){
if(flag==5)
flag=6;
elseflag=4;
}//有前置且有后置FLAG=6,只有后置=4
else{
if(flag==1)
flag=2;
}//前后都没有置2
switch(flag){
case5:
pf->end=pf->end+p3->len;前置空闲块
pf->len=pf->len+p3->len;
break;
case4:
pe->start=pe->start-p3->len;只有后置
pe->len=pe->len+p3->len;
break;
case2:
area*p8;
p8=newarea;
p8->start=p3->start;
p8->len=p3->len;
p8->sign=0;
p8->end=p3->end;
p8->next=freehead;
freehead=p8;
break;
case6:
pf->end=pe->end;有前置与后置
pf->len=pf->len+pe->len+p3->len;
if(pe->next==NULL){
pe1->next=NULL;
deletepe;
}
else{
if(pe==freehead){
freehead=pe->next;
deletepe;
}
else{
pe1->next=pe->next;
deletepe;
}
}
break;
default:
break;
}
}
voidsetfree(){释放进程
intchose;
cout<<"选择一个要释放的任务:
";
cin>>chose;
area*p7=usedhead,*p2;
while(p7!
=NULL){//寻找有无此进程
if(p7->sign!
=chose){
p2=p7;
p7=p7->next;
}
elsebreak;
}
if(p7==NULL){
cout<<"没有此进程,释放内存失败,返回修改!
"< return; } inserfree(p7);//将其释放的内存插入空闲块中 if(p7==usedhead&&p7->next==NULL) usedhead=NULL; else{ if(p7->next==NULL){ p2->next=NULL; deletep7; }//将次进程从已分配表中删除 else{ if(p7==usedhead){ usedhead=p7->next; deletep7; } else{ p2->next=p7->next; deletep7; } } } cout<<"成功释放所选任务的内存! 当前内存状况为: "< print(freehead); print(usedhead); cout< } voidinserused(area*p3,intnum,intneed){//将新项插入已分配表中 area*p5; if(usedhead==NULL){ p5=newarea; p5->start=p3->start; p5->len=need; p5->sign=num; p5->end=p3->start+need; p5->next=NULL; usedhead=p5;} else{ p5=newarea; p5->start=p3->start; p5->len=need; p5->sign=num; p5->end=p3->start+need; p5->next=usedhead; usedhead=p5; } } voidcorrect(area*p3,intneed1){修改列表 p3->len=p3->len-need1; p3->start=p3->start+need1; } voidcreate(){创建地址长度 area*p1; p1=newarea; p1->start=0; p1->end=999; p1->len=999; p1->sign=0; p1->next=NULL; freehead=p1; } voidask1(area*freehead){//读文件初始化,只用一次 intnum,need; area*p3=freehead; ifstreaminfile("123.TXT"); while(infile>>num){ infile>>need; if(p3->len cout<<"内存不足,分配失败! "< return; } else inserused(p3,num,need); correct(p3,need); } } voidask(area*freehead){申请内存 intnum,need; area*p3=freehead,*p31=freehead; cout<<"inputnumandneed! "< cin>>num; cin>>need; while(p3! =NULL){ if(p3->len p31=p3; p3=p3->next; } elsebreak; } if(p3==NULL){ cout<<"内存不足,分配失败! "< return; } inserused(p3,num,need); correct(p3,need); freehead=delempty(); cout<<"成功分配申请,当前内存状况为: "< print(freehead); print(usedhead); cout< } voidprint(area*pp){显示页面 area*p; p=pp; cout<<"────────────────────────────\n"; if(p==NULL) {cout<<"emptylist! "< cout<<"────────────────────────────\n";return;} else do{ cout<<"start: "< "< "< "< p=p->next; }while(p! =NULL); cout<<"────────────────────────────\n"; } intmain() {intyourchose,flag1=0,flag2=0; intwhat; cout<<">>>>现在初始化内存>>>>>>>\n"; cout<<"请选择: 1.手动初始化2.读取文件初始化: "; cin>>flag2; create(); if(flag2==2)ask1(freehead); cout<<"内存初始状态为: \n"
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 动态 可变 分区 存储 管理 模拟 系统