课程设计报告3277李鑫.docx
《课程设计报告3277李鑫.docx》由会员分享,可在线阅读,更多相关《课程设计报告3277李鑫.docx(25页珍藏版)》请在冰豆网上搜索。
课程设计报告3277李鑫
上海电力学院
课程设计报告
课程名称:
操作系统原理
题目名称:
可变分区存储管理
姓名:
李鑫学号:
20103277
班级:
2010251同组姓名:
无
课程设计时间:
2013.1.7~2013.1.11
评语:
成绩:
课程设计题目
一、设计内容及要求
(要求注明小组分工情况)
设计内容:
可变分区存储管理。
设计一个可变分区存储管理方案,模拟实现:
主存的分配和回收,地址变换。
输入:
(1)输入进程名称及使用内存的大小(创建进程);
(2)结束某一个指定的进程。
(3)逻辑地址。
输出:
显示内存使用状况;每一个进程占据的内存;物理地址。
使用的分配算法包括:
(1)首次适应算法;
(2)最佳适应算法;
(3)最差适应算法;
二、详细设计
1)原理概述
内存分配有固定分区分配方式和动态分区分配方式,固定分区分配是最简单的一种可以运行多道程序的存储管理方式。
它是将内存空间划分为若干个固定大小的区域,在每个分区中只装入一道作业,它把用户空间划分为几个分区,允许有多道作业并发运行。
它的分区划分方法有两种:
1、分区大小相等,即使所有的内存分区大小相同。
2、分区大小不等。
它的分配方式存在缺点,即缺乏灵活性,浪费内存,如果一个进程申请很少的一块内存,那么它会占据整个内存分区,即使还有大部分空闲,例如一个进程有5k,申请了分区号4的内存,虽然还有123k内存,但是其他进程也不可以利用,只有进程结束了,其他进程才可以利用,内存十分浪费。
分区号
起始地址
大小
状态
1
20
12
已分配
2
32
32
已分配
3
64
64
已分配
4
128
128
未分配
在上边的基础上,便产生了可变分区分配方式。
它是根据进程的实际需要,动态的为它分配内存空间,避免了上边的固定分区分配方式的缺点。
它涉及到分区分配中所用的数据结构、分区分配算法和分区的分配与回收操作这三个问题。
1、分区分配中的数据结构
在这里我使用了空闲分区表。
在系统中设置一张空闲分区表,用于记录每个空闲分区的情况。
每个空闲分区占一个表目,表中包括了分区号、分区始址、分区大小、和一个代表它是空闲的状态。
在系统中还有一张已分配表,用于记录已经分配给相应进程的内存,它的表目与空闲分区表一样,状态是已分配。
2、分区分配算法
A首次适应算法(firstfit)
每次分配时,总是从未分配区表头顺序查找未分配表或链表,找到第一个能满足长度要求的空闲区为止。
分割这个找到的未分配区,一部分分配给作业,另一部分仍为空闲区。
这种分配算法优先利用主存低地址空闲分区,从而,保留了高地址的大的空闲区。
但由于低地址空闲分区不断被分割,既可能将大的空间分割掉,也造成低地址部分有较多难以使用的“碎片”。
作为改进,可把空闲区按地址从小到大排列在未分配表或链表中,因为,为作业分配主存空间时从低地址部分的空闲区开始查找,可使高地址部分尽可能少用,以保持一个大的空闲区,有利于大作业的装入。
但是,这给回收分区带来一些麻烦,每次收回一个分区后,必须搜索未分配区表或链表来确定它在表格或链表中的位置且要移动相应的登记项。
B最佳适应算法(bestfit)
该算法要扫描整个未分配区表或链表,从空闲区中挑选一个能满足作业要求的最小分区进行分配。
这种算法可保证不去分割一个更大的区域,使装入大作业时比较容易得到满足。
采用这种分配算法时可把空闲区按长度以递增顺利排列,查找时总是从最小的一个区开始,直到找到一个满足要求的分区为止。
按这种方法,在回收一个分区时也必须对分配表或链表重新排列。
最优适应分配算法找出的分区如果正好满足要求则是最合适的了,如果比所要求的略大则分割后使剩下的空闲区就很小,以致无法使用。
C最坏适应算法(worstfit)
最坏适应分配算法要扫描整个未分配区表或链表,总是挑选一个最大的空闲区分割给作业使用,其优点是可使剩下的空闲区不至于太小,对中、小作业有利。
采用这种分配算法时可把空闲区按长度以递减顺序排列,查找时只要看第一个分区能否满足作业要求,这样使最坏适应分配算法查找效率很高。
3、分区分配操作
它主要涉及到分区的分配内存和回收内存问题。
A分配内存
B回收内存
内存回收有四种回收状态状态,比较复杂点。
如下图:
X为将要回收的内存,A、B为正在运行的进程,回收X有四种合并状态。
黑色区域为回收后的空闲内存。
2)主要数据结构
定义了内存分区结构体,在此基础上定义了此结构体的对象free[100]和used[100],分别表示空闲分区表和已分配的分区表,他们的最大值都是100,而且结构也相同。
Procnum是全局变量,用于已分配的进程分区号,每个进程唯一。
structtable
{
inttablenum;//分区号
intstartaddr;//起始地址
intlength;//长度
charstate[10];//分配状态
};
tablefree[100];//空闲分区表
tableused[100];//已分配分区表
intfreelength;//空闲分区表长度
intusedlength;//已分配分区表长度
intprocnum=0;//进程分区号
3)算法(流程图)
程序状态流程图
内存分配流程图
4)源程序文件名
os课程设计1
#include
#include
structtable
{
inttablenum;//分区号
intstartaddr;//起始地址
intlength;//长度
charstate[10];//分配状态
};
tablefree[100];//空闲分区表
tableused[100];//已分配分区表
intfreelength;//空闲分区表长度
intusedlength;//已分配分区表长度
intprocnum=0;//进程分区号
voidinitial();//初始化分区
voidfirstfit();//首次适应算法
voidbestfit();//最佳适应算法
voidworstfit();//最坏适应算法
voidterminal();//结束进程
inttransfer();//逻辑地址转换
voidprint();//打印输出
intmain()
{
cout<<"///////////////////可变分区存储管理系统///////////////////"<initial();
ints,n,x=1;
print();
while(x)
{
cout<<"//////////////////////////////////////////////////////////"<cout<<"--1、创建进程(进程名内存大小);"<<<"--2、结束进程(进程名);"<<<"--3、逻辑地址转换;"<<<"--4、退出"<";
cin>>n;
switch(n)
{
case1:
cout<<"--使用算法1、首次适应算法;2、最佳适应算法;3、最差适应算法"<";
cin>>s;
switch(s)
{
case1:
firstfit();
break;
case2:
bestfit();
break;
case3:
worstfit();
break;
}
print();
break;
case2:
terminal();
print();
break;
case3:
transfer();
break;
case4:
x=0;
break;
}
}
return0;
}
voidinitial()
{
for(inti=0;i<100;i++)
{
free[i].tablenum=-1;
free[i].startaddr=-1;
free[i].length=0;
strcpy(free[i].state,"free");
used[i].tablenum=-1;
used[i].startaddr=-1;
used[i].length=0;
strcpy(used[i].state,"used");
}
freelength=0;
usedlength=0;
free[0].tablenum=0;
free[0].startaddr=0;
free[0].length=50;
free[1].tablenum=1;
free[1].startaddr=50;
free[1].length=100;
free[2].tablenum=2;
free[2].startaddr=150;
free[2].length=80;
free[3].tablenum=3;
free[3].startaddr=230;
free[3].length=40;
free[4].tablenum=4;
free[4].startaddr=270;
free[4].length=200;
free[5].tablenum=5;
free[5].startaddr=470;
free[5].length=150;
freelength=6;
}
voidprint()
{
cout<<"//////////////////////////////////////////////////////////"<cout<<"空闲分区表:
"<for(inti=0;i{
cout<}
cout<<"已分配分区表:
"<for(i=0;i{
cout<}
cout<<"//////////////////////////////////////////////////////////"<}
inttransfer()
{
intm;
cout<<"输入要转换的分区号:
"<";
cin>>m;
for(inti=0;i{
if(used[i].tablenum==m)
{
cout<(物理地址)"<return1;
}
}
cout<<"逻辑分区号输入错误。
"<return0;
}
voidfirstfit()
{
charprocname[20];
intproclength;
inti,j,flag,t;
cout<<"输入进程的名称和大小:
"<";
cin>>procname;
cin>>proclength;
for(i=0;i{
if(free[i].length>=proclength)
{
flag=1;
}
}
if(flag==0)
{
cout<}
else
{
t=0;
i=0;
while(t==0)
{
if(free[i].length>=proclength)
{
t=1;
}
i++;
}
i--;
used[usedlength].startaddr=free[i].startaddr;
strcat(used[usedlength].state,procname);
used[usedlength].length=proclength;
used[usedlength].tablenum=procnum;
usedlength++;
procnum++;
if(free[i].length>proclength)
{//空闲区域大于申请的区域
free[i].startaddr+=proclength;
free[i].length-=proclength;
}
else
{//空闲区域等于申请的区域
for(j=i;j{
free[j]=free[j+1];
}
freelength--;
}
cout<<"内存空间分配成功"<}
}
voidbestfit()
{
//intprocnum=0;
charprocname[20];
intproclength;
inti,j,flag,t;
cout<<"输入进程的名称和大小:
"<";
cin>>procname;
cin>>proclength;
flag=0;
for(i=0;i{
if(free[i].length>=proclength)
{
flag=1;
}
}
if(flag==0)
{
cout<}
else
{
t=0;
i=0;
while(t==0)
{
if(free[i].length>=proclength)
{
t=1;
}
i++;
}
i--;
for(j=0;j{
if((free[j].length>=proclength)&&(free[j].length{
i=j;
}
}
used[usedlength].startaddr=free[i].startaddr;
strcat(used[usedlength].state,procname);
used[usedlength].length=proclength;
used[usedlength].tablenum=procnum;
usedlength++;
procnum++;
if(free[i].length>proclength)
{
free[i].startaddr+=proclength;
free[i].length-=proclength;
}
else
{
for(j=i;j{
free[j]=free[j+1];
}
freelength--;
}
cout<<"内存空间分配成功"<}
}
voidworstfit()
{
//intprocnum=0;
charprocname[20];
intproclength;
inti,j,flag,t;
cout<<"输入进程的名称和大小:
"<";
cin>>procname;
cin>>proclength;
flag=0;
for(i=0;i{
if(free[i].length>=proclength)
{
flag=1;
}
}
if(flag==0)
{
cout<}
else
{
t=0;
i=0;
while(t==0)
{
if(free[i].length>=proclength)
{
t=1;
}
i++;
}
i--;
for(j=0;j{
if((free[j].length>=proclength)&&(free[j].length>free[i].length))
{
i=j;
}
}
used[usedlength].startaddr=free[i].startaddr;
strcat(used[usedlength].state,procname);
used[usedlength].length=proclength;
used[usedlength].tablenum=procnum;
usedlength++;
procnum++;
if(free[i].length>proclength)
{
free[i].startaddr+=proclength;
free[i].length-=proclength;
}
else
{
for(j=i;j{
free[j]=free[j+1];
}
freelength--;
}
cout<<"内存空间分配成功"<}
}
voidterminal()
{
charprocname[20];
intproclength;
inti,j,flag,p=0;
intstart;
intlength;
cout<<"输入要结束的进程名:
"<";
cin>>procname;
charbuffer[20];
strcpy(buffer,"used");
strcat(buffer,procname);
flag=-1;
for(i=0;i{//寻找指定名称的作业
if(!
strcmp(used[i].state,buffer))
{
flag=i;
start=used[i].startaddr;
length=used[i].length;
}
}
if(flag==-1)
{
cout<<"没有这个进程名"<}
else
{
for(i=0;i{
if((free[i].startaddr+free[i].length)==start)//与前边的邻接
{
if(((i+1){
free[i].length=free[i].length+free[i+1].length+length;//三块合并
for(j=i+1;j{
free[j]=free[j+1];
}
freelength--;
p=1;
}
else//两块合并
{
free[i].length+=length;
p=1;
}
}
if(free[i].startaddr==(start+length))//与后边邻接
{
free[i].startaddr=start;
free[i].length+=length;
p=1;
}
}
if(p==0)//既不与前邻接,也不与后邻接
{
free[freelength].startaddr=start;
free[freelength].length=length;
free[freelength].tablenum=free[freelength-1].tablenum+1;
freelength++;
}
for(i=flag;i{
used[i]=used[i+1];
}
usedlength--;
}
}
执行文件名
三、实验结果与分析(要有结果截图)
初始界面
首次适应算法创建进程a30
最佳适应算法创建进程b90
最差适应算法创建进程c100
结束进程b
逻辑地址转换:
输入分区号2,找到了物理地址270
退出程序
四、设计总结
可变分区存储管理