可变分区存储管理实验报告程序设计思路和感悟参考模板.docx
《可变分区存储管理实验报告程序设计思路和感悟参考模板.docx》由会员分享,可在线阅读,更多相关《可变分区存储管理实验报告程序设计思路和感悟参考模板.docx(15页珍藏版)》请在冰点文库上搜索。
可变分区存储管理实验报告程序设计思路和感悟参考模板
实验题目:
可变分区存储管理
一、实验目的
可变分区存储管理方式是操作系统中存储管理的重要方式,其主要思想是用户作业进行连续存储,每次按照用户的请求,如果内存中有能满足用户作业大小的空闲区,就采用不同的算法分配给用户,否则,不分配,可变分区容易产生外零头。
分区分配算法包括最佳适应算法、最坏适应算法、首次适应算法等。
通过本实验可加深学生对存储器管理方式的把握以及分配算法的理解,并提高程序设计的能力。
二、实验环境
个人PC机WindowsXP操作系统I5-2400CPU3.10Ghz2GB内存
C-FreeC语言程序设计软件
三、实验的重点和难点
可变分区的的收回
四、实验内容
利用C语言或C++语言或Java语言实现可变分区存储管理,具体要求如下:
1.以一个一维数组模拟内存,数组类型为整型,共计1000个元素;
2.用一个单链表表示可变分区空闲表,链表每个结点表示一个空闲区,每个结点信息包括起始地址、大小。
3.分区分配算法采用最佳适应算法、首次适应算法,并将算法用函数实现。
4.自己假设几个作业,包括作业的名称、大小,进入系统的顺序。
5.初始内存中没有任何作业,随着用户输入的每一个作业的到来,动态为其分配内存。
6.使用的算法用户要能够随时更换。
五、实验结果或实验代码
(1)可变式分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区个数可以调整。
当要装入一个作业时,根据作业需要的内存量,查看是否有足够的空闲空间,若有,则按需求量分割一部分给作业;若没有,则作业等待。
随着作业的装入、完成,内存空间被分割成许多大大小小的分区。
有的分区被作业占用,有的分区空闲。
例如,某时刻内存空间占用情况如图1所示。
操作系统(10KB)
作业1(10KB)
空闲区2(146KB)
作业4(25KB)
空闲区1(20KB)
作业2(45KB)
图1内存空间占用情况
65K
110K
256K
0
20K
45K
10K
为了说明那些分区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,如表1所示。
表1空闲区说明表
起始地址
长度
状态
45K
20K
未分配
110K
146K
未分配
空表目
空表目
空表目
……
……
……
其中,起始地址指出个空闲区的内存起始地址,长度指出空闲区的大小。
状态(未分配:
该栏目记录的是有效空闲区)
状态(空表目:
没有登记信息)
由于分区个数不定,所以空闲区说明表中应该有足够的空表目项。
否则造成溢出,无法登记。
同样,再设一个已分配表,记录作业或进程的内存占用情况。
(2)当有一个新作业要求装入内存时,必须查空闲区说明表,从中找出一个足够大的空闲区。
有时找到的空闲区可能大于作业需求量,这时应将空闲区一分为二。
一个分给作业,另外一个作为空闲区留在空闲区表中。
为了尽量减少由于分割造成的碎片,尽可能分配低地址部分的空闲区,将较大空闲区留在高地址端,以利于大作业的装入。
为此在空闲区表中,按空闲区首地址从低到高进行登记。
为了便于快速查找,要不断地对表格进行紧缩,即让“空表目”项留在表的后部。
其分配框图如图2所示。
开始
申请XK内存
J=0
J=J+1
查看第J个表目的登记项
状态为“未分
配”吗
长度〉=XK?
J为空闲区说明表的最后一个表目?
置状态为“空表目”
将空表目向后移
长度=长度-XK
始址=始址+XK
登记已分配区表和空闲区表,输出系统中各数据结构的值。
返回分配给作业的内存始址
作业等待
返回
图2首次适应算法分配框图
Y
Y
N
N
小于
大于
等于
(3)当一个作业执行完成时,作业所占用的分区应归还给系统。
在归还时要考虑相邻空闲区合并的问题。
作业的释放区与空闲区的邻接分以下4种情况考虑:
●释放区下邻(低地址邻接)空闲区;
●释放区上邻(高地址邻接)空闲区;
●释放区上下都与空闲区邻接;
●释放区与空闲区不邻接。
首次适应算法回收框图如图3所示。
图3首次适应算法回收框图
有等待装入的作业吗?
有与释放区下邻的空闲区吗?
L=L+上邻空闲区长度
有与释放区下邻的空闲区吗?
开始
S=释放区始址
L=释放区长度
查空闲区说明表
有与释放区的高地址邻接(上邻)的空闲区吗?
在空闲区说明表中找一空表目登记:
地址=S
长度=L
状态=未分配
按地址顺序调整和紧缩空闲区说明表
把上邻空闲区登记栏中的状态置为“空表目”,且将空表目向后调整
唤醒等待的作业并返回
把上邻空闲区登记栏中的始址改为S,长度改为L
把下邻空闲区登记栏中的长度改为:
长度=长度+L
返回
Y
Y
Y
Y
N
N
N
N
(4)请按首次适应算法设计内存分配和回收程序。
以表2当前使用的基础,初始化空闲区和已分配区说明表值。
设计一个作业申请队列以及作业完成后的释放顺序,实现内存的分配与回收。
把空闲区说明表的变化情况以及各作业的申请、释放情况显示或打印出来。
表2空闲区说明表
起始地址
长度
状态
20K
20KB
1
80K
50KB
1
150K
100KB
1
300K
30KB
0(空表目)
600K
100KB
1
……
……
空表目
……
……
……
程序代码
#include"iostream.h"
#include"stdio.h"
#include"stdlib.h"
#include"conio.h"
#definen10//假定系统允许的最大作业数量为n
#definem10//假定系统允许的空闲区表最大为m
#defineminisize1000
struct
{
floataddress;//已分分区起始地址
floatlength;//已分分区长度,单位为字节
intflag;//已分分区表登记栏标志,用"0"表示空栏目,实验中只支持一个字符的作业名
}used_table[n];//已分分区表
struct
{
floataddress;//空闲区起始地址
floatlength;//空闲区长度,单位为字节
intflag;//空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配
}free_table[m];//空闲区表
intallocate(charJ,floatxk)//采用最有分配法分配xk大小的空间
//charJ;
//floatxk;
{
inti,k;
floatad;
k=-1;
for(i=0;iif(free_table[i].length>=xk&&free_table[i].flag==1)
if(k==-1||free_table[i].lengthk=i;
if(k==-1)//未找到可用空闲区,返回
{
cout<<"无可用空闲区"<return0;
}
//找到可用空闲区,开始分配:
若空闲区大小与分配的空间差小于minisize,则空闲区全部分配:
//若空闲区大小与要求分配的空间差大于minisize,则从空闲区划出一部分分配
if(free_table[k].length-xk<=minisize)
{
free_table[k].flag=0;
ad=free_table[k].address;
xk=free_table[k].length;
}
else
{
free_table[k].length=free_table[k].length-xk;
ad=free_table[k].address+free_table[k].length;
}
//修改分配区表
i=0;
while(used_table[i].flag!
=0&&i{
i++;
if(i>=n)
{
cout<<"无表目填写已分分区,错误"<//修正空闲区表
if(free_table[k].flag==0)//前面找到的是整个空闲区
free_table[k].flag=1;
else//前面找到的是某个空闲区的一部分
free_table[k].length=free_table[k].length+xk;
return0;
}
else
{
used_table[i].address=ad;
used_table[i].length=xk;
used_table[i].flag=J;
}
return1;
}//内存分配函数结束
}
intreclaim(charJ)//回收作业名为J的作业所占内存空间
//charJ;
{
inti,k,j,s,t;
floatS,L;
//寻找已分分区表中对应登记项
s=0;
while((used_table[s].flag!
=J||used_table[s].flag==0)&&ss++;
if(s>=n)//在已分分区表中找不到名字为J的作业
{
cout<<"找不到该作业"<return0;
}
//修改已分分区表
used_table[s].flag=0;
//取得归还分区的起始地址S和长度L
S=used_table[s].address;
L=used_table[s].length;
j=-1;
k=-1;
i=0;
//寻找回收分区的上下邻空闲区,上邻表目k,下邻表目j
while(i{
if(free_table[i].flag==0)
{
if(free_table[i].address+free_table[i].length==S)
k=i;//找到上邻
if(free_table[i].address==S+L)
j=i;//找到下邻
}
i++;
}
if(k!
=-1)
if(j!
=-1)//上邻空闲区,下邻空闲区,三项合并
{
free_table[k].length=free_table[j].length+free_table[k].length+L;
free_table[j].flag=0;
}
else//上邻空闲区,下邻非空闲区,与上邻合并
free_table[k].length=free_table[k].length+L;
else
if(j!
=-1)//上邻非空闲区,下邻为空闲区,与下邻合并
{
free_table[j].address=S;
free_table[j].length=free_table[j].length+L;
}
else//上下邻均为非空闲区,回收区域直接填入
{//在空闲区表中寻找空栏目
t=0;
while(free_table[t].flag==1&&tt++;
if(t>=m)//空闲区表满,回收空间失败,将已分分区表复原
{
cout<<"内存空闲表没有空间,回收空间失败"<used_table[s].flag=J;
return0;
}
free_table[t].address=S;
free_table[t].length=L;
free_table[t].flag=1;
}
return1;
}//内存归还函数结束
voidmain()
{
inti,a;
floatxk;
charJ;
//空闲区表初始化
free_table[0].address=10240;
free_table[0].length=102400;
free_table[0].flag=1;
for(i=1;ifree_table[i].flag=0;
//已分分区表初始化
for(i=0;iused_table[i].flag=0;
while
(1)
{
cout<<"选择功能项(0-推出,1-分配内存,2-回收内存,3-显示内存)"<cout<<"选择功项(0~3):
";
cin>>a;
switch(a)
{
case0:
exit(0);//a=0程序结束
case1:
//a=1分配内存空间
cout<<"输入作业名J和作业所需长度xk:
";
cin>>J>>xk;
allocate(J,xk);//分配内存空间
break;
case2:
//a=2回收内存空间
cout<<"输入要回收分区的作业名";
cin>>J;
reclaim(J);//回收内存空间
case3:
//a=3显示内存情况,输出空闲区表和已分分区表
cout<<"输出空闲区表:
"<cout<<"起始地址分区长度标志"<for(i=0;icout<cout<<"按任意键,输出已分分区表"<getch();
cout<<"输出已分分区表:
"<cout<<"起始地址分区长度标志"<for(i=0;iif(used_table[i].flag!
=0)
cout<else
cout<break;
default:
cout<<"没有该选项"<}
}
}
为可变分区管理方式的工作过程画出流程图;
六、实验过程遇到的问题及其解决
当系统实现分配系统资源时,应该首先判断与本作业相匹配的空间资源大小,这样才能使得系统的资源利用率提高。
然后再进行系统资源分配。
初始使用的资源没有按照这种分配思路,而是直接在系统中查找到首先与之相匹配的空块,导致系统的资源利用率大大减小。
七、实验总结
通过这次关于可变分区存储管理的操作系统实验,我了解了操作系统关于内存共享、分页的过程、未分页合并内存与分页合并内存的管理以及如何提高分页的效率。
关于概念性的内容有了更深层次的理解例如:
分页就是将信息从主内存移动到磁盘进行临时存储的过程。
应用程序经常需要彼此通信和共享信息。
为了提供这种能力,Windows必须允许访问某些内存空间而不危及它和其他应用程序的安全性和完整性。
使我对操作系统的作业功能有了更加深化一步的认识。
友情提示:
范文可能无法思考和涵盖全面,供参考!
最好找专业人士起草或审核后使用,感谢您的下载!