存储器管理实验报告.docx
《存储器管理实验报告.docx》由会员分享,可在线阅读,更多相关《存储器管理实验报告.docx(22页珍藏版)》请在冰豆网上搜索。
存储器管理实验报告
操作系统实验报告
存储器管理
学院电 信 学 院
专业计算机科学与技术
班级14 级计科一班
实验题目动态分区分配
实验组别第三组
指导老师曹华
1
学 号
20141030111
20141030112
20141030113
20141030114
姓 名
张 丹
陈云云
张伟军
李瑞玲
实验项目
二
题 目
动态分区分配
一、实验目的
了解动态分区分配方式中使用的数据结构和分配算法,并进一步加深对动态分区
存储管理方式及其实现过程的理解。
二、实验内容
用C语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程 alloc()
和回收过程 free()。
其中,空闲分区通过分区链来管理,在进行内存分配时,系统优先
使用空闲区低端的空间。
请分别用首次适应算法和最佳适应算法进行内存块的分配和回收,要求每次分配和回
收后显示出空闲内存分区链的情况。
三、实验主要仪器设备
软件环境:
VC++6编程环境
四、实验原理及设计方案
1.实验原理:
可变分区调度算法有:
最先适应分配算法,循环首次适应算法,最佳适应算法,最坏
适应算法。
首次适应算法(First-fit):
当要分配内存空间时,就查表,在各空闲区中查找满足大
小要求的可用块。
只要找到第一个足以满足要求的空闲块就停止查找,并把它分配出
去;如果该空闲空间与所需空间大小一样,则从空闲表中取消该项;如果还有剩余,
则余下的部分仍留在空闲表中,但应修改区分大小和分区始址。
用户提出内存空间的申请:
系统根据申请者的要求,按照一定的分配策略分析内存空
间的使用情况,找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还
内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
最佳适应算法(Best-fit):
当要分配内存空间时,就查找空闲表中满足要求的空闲块,
并使得剩余块是最小的。
然后把它分配出去,若大小恰好合适,则直按分配;若有剩
余块,则仍保留该余下的空闲分区,并修改分区大小的起始地址。
内存回收:
将释放作业所在内存块的状态改为空闲状态,删除其作业名,设置为空,
并判断该空闲块是否与其他空闲块相连,若释放的内存空间与空闲块相连时,则合并
为同一个空闲块,同时修改分区大小及起始地址。
每当一个进程被创建时,内存分配程序首先要查找空闲内存分区链,从中寻找一
个合适的空闲块进行划分,并修改空闲内存分区链,系统根据回收区的首址,从空闲
区链中找到相应的插入点,此时出现如下四种情况:
(1) 回收区与插入点的前一个空闲区F1相邻接,此时可将回收区直接与F1合并,
并修改F1的大小;
(2) 回收区与插入点的后一个空闲分区F2相邻接,此时可将回收区直接与F2合并,
并用回收区的首址作为新空闲区的首址,大小为二者之和;
(3) 回收区同时与插入点的前后两个空闲分区邻接,此时需将三者合并;
(4) 回收区不与任何一个空闲区邻接,此时应建一新的表项
2.主要数据结构的说明
定义一个空闲区说明表结构
2
struct freearea {
int ID;//分区号
long size; //分区大小
long address; //分区地址
int state;//状态
}ElemType;
线性表的双向链表存储结构
Struct DuLNode//double linked list
{
ElemType data;
struct DuLNode *prior; //前趋指针
struct DuLNode *next; //后继指针
}DuLNode,*DuLinkList;
算法;
首次适应算法:
是在分配内存时,从链首开始顺序查找,直到找到一个大小能够
满足要求的分区,即进行分配。
最佳适应算法:
是在分配内存时,从链首开始顺序查表,查找到链尾,并记录一
个大小不小于要求的分区的最小分区,在查找完毕后进行分配。
3.程序流程图
首次适应算法
空闲区首地址
已到末端?
N
无法
该区大小>=n?
N
取下一块
分配
Y
该区大小=n?
Y
调整链表
返回分配起始地址
N
截取长度并
修改链表
最佳适应算法
开始
3
p=av,p=av
F
T
TF
4.实验程序
首次适应算法
#include
#include
#include
#include
#define N 10000
int n1;//空闲分区的个数
int n2;//作业区的个数
struct kongxian
{
int start; //起址
int end; //结束
int length; //长度
4
}kongxian[N];
struct zuoye
{
int start; //起址
int end;//结束
int length; //长度
}zuoye[N];
int cmp1(const void *a,const void *b)
{
return (*(struct kongxian *)a).start-
(*(struct kongxian *)b).start;
}
int cmp2(const void *a,const void *b)
{
return (*(struct zuoye *)a).start-
(*(struct zuoye *)b).start;
}
void init()
{
n1=1; //初始时只有一个空闲区
n2=0; //初始没有作业
kongxian[0].start=0;
kongxian[0].end=1023;
kongxian[0].length=1024;
}
void print1() //打印空闲分区
{
int i;
for(i=0;iprintf("空闲分区 ID:
%d起止:
%d
结束:
%d长度:
%d\n",i,kongxian[i].
start,kongxian[i].end,kongxian[i].length);
}
void print2() //打印作业分区
{
int i;
for(i=0;iprintf("作业分区 ID:
%d起止:
%d
结束:
%d 长度:
%d\n",i,zuoye[i].start,zuoye[i].
end,zuoye[i].length);
}
int main()
{
int i,j,t,len,flag,id;
int front,middle, behind;
int t1,t2;
init();
print1();
printf("输入 1 装入新作业,输入 0 回
收作业,输入-1 结束\n");
while(scanf("%d",&t)!
=EOF)
{
if(t==1) //装入新作业
{
printf("请输入作业的占用空间
的长度 ");
scanf("%d",&len);
flag=0;
for(i=0;i{
if(kongxian[i].length>=len) //首次适应算法
{
flag=1;
break;
}
}
if(!
flag)
{
printf("内存分配失败\n");
}
else
{
zuoye[n2].start=kongxian[i].start;
zuoye[n2].end=zuoye[n2].start+len;
zuoye[n2].length=len;
n2++; //作业数加 1
if(kongxian[i].length==len) //该分区
全部用于分配,删除该空闲分区
{
for(j=i;j{
kongxian[j].start=kongxian[j+1].star
t;
kongxian[j].end=kongxian[j+1].end;
kongxian[j].length=kongxian[j+1].length;
}
n1--;
}
5
else//该空闲分
区部分用于分配,剩余的留在空闲分区中
{
kongxian[i].start+=len;
kongxian[i].length-=len;
}
}
}
else if(t==0)
{
printf("输入要回收的作
业 ID ");
scanf("%d",&id);
front=middle=behind=0;
for(i=0;i{
if(kongxian[i].start>zuoye[id].end)
break;
if(kongxian[i].end==zuoye[id].start) //待
回收的作业上面有空闲分区
{
front=1;
t1=i;
}
if(kongxian[i].start>zuoye[id].end)
{
behind=1;
t2=i;
}
}
if(!
front&&!
behind)
{
kongxian[n1].start=zuoye[id].start;
kongxian[n1].end=zuoye[id].end;
kongxian[n1].length=zuoye[id].length;
n1++;
qsort(kongxian,n1,sizeof(struct
kongxian),cmp1);
for(j=id;j{
zuoye[j].start=kongxian[j+1].start;
zuoye[j].end=zuoye[j+1].end;
zuoye[j].length=zuoye[j+1].length;
}
n2--;
}
if(front&&behind)
middle=1;
if(front&&!
behind)
{
kongxian[t1].end+=zuoye[id].length;
kongxian[t1].length+=zuoye[id].length;
for(j=id;j{
zuoye[j].start=zuoye[j+1].start;
zuoye[j].end=zuoye[j+1].end;
zuoye[j].length=zuoye[j+1].length;
}
n2--;
}
if(middle)
{
kongxian[t1].end=kongxian[t2].end;
kongxian[t1].length+=(zuoye[id].length+k
ongxian[t2].length);
for(j=t2;j{
kongxian[j].start=kongxian[j+1].start;
kongxian[j].end=kongxian[j+1].end;
kongxian[j].length=kongxian[j+1].length;
}
n1--;
for(j=id;j{
zuoye[j].start=kongxian[j+1].start;
zuoye[j].end=zuoye[j+1].end;
zuoye[j].length=zuoye[j+1].length;
}
n2--;
}
if(front&&!
behind)
{
kongxian[t1].end-=zuoye[id].length;
kongxian[t1].length+=zuoye[id].length;
for(j=id;j{
zuoye[j].start=zuoye[j+1].start;
zuoye[j].end=zuoye[j+1].end;
6
zuoye[j].length=zuoye[j+1].length;
}
n2--;
}
}
else
{
printf("操作结束\n");
最佳适应算法
#include
#include
#include
#include
struct kongkuai
{ int startaddr;
int size;
int flag;
}kongxq[6]={{10,30,1},{100,60,1},{200,80,1},{3
00,60,1},{400,180,1},{700,200,1}};
int allocate(int jobsize)
{
int i;
int t=0;
for(i=0;i<6;i++)
if(kongxq[i].flag==1&&kongxq[i].size>job
size)
{
kongxq[i].startaddr+=jobsize;
kongxq[i].size-=jobsize;
t=1;
returnkongxq[i].startaddr-
jobsize;
}
else
if(kongxq[i].flag==1&&kongxq[i].size==jo
bsize)
{
kongxq[i].flag=0;
t=1;
return kongxq[i].startaddr;
}
if(t==0)
return 0;
return 1;
break;
}
print1();
print2();
}
return 0;
}
}
void circle()
{
int i,j;
struct kongkuai temp;
for(i=0;i<6;i++)
for(j=0;j<6;j++)
if(kongxq[j].size>kongxq[j+1].size)
{
temp.startaddr=kongxq[j].startaddr;
temp.size=kongxq[j].size;
temp.flag=kongxq[j].flag;
kongxq[j].startaddr=kongxq[j+1].startad
dr;
kongxq[j].size=kongxq[j+1].size;
kongxq[j].flag=kongxq[j+1].flag;
kongxq[j+1].startaddr=temp.startaddr;
kongxq[j+1].size=temp.size;
kongxq[j+1].flag=temp.flag;
}
for(i=0;i<6;i++)
for(j=0;j<6;j++)
if(kongxq[j].flag==0&&kongxq[j+1].flag==
1)
{
temp.startaddr=kongxq[j].startaddr;
temp.size=kongxq[j].size;
temp.flag=kongxq[j].flag;
kongxq[j].startaddr=kongxq[j+1].startad
dr;
kongxq[j].size=kongxq[j+1].size;
kongxq[j].flag=kongxq[j+1].flag;
kongxq[j+1].startaddr=temp.startaddr;
kongxq[j+1].size=temp.size;
kongxq[j+1].flag=temp.flag;
7
}
}
void callback()
{
int s,len,t1=0,t2=0,t3=0,i,j;
printf("请输入回收区的起始地址:
\n");
scanf("%d",&s);
printf("请输入回收区的大小:
\n");
scanf("%d",&len);
for(i=0;i<6;i++)
{
if((kongxq[i].startaddr==s+len)&&(kongxq[i].fl
ag==1))
{
len+=kongxq[i].size;
t1=1;
for(j=0;j<6;j++)
if((kongxq[j].startaddr+kongxq[j].size==s)
&&(kongxq[j].flag==1))
{
kongxq[i].flag=0;
kongxq[j].size=kongxq[j+1].size+len;
t2=1;
break;
}
if(t2==0)
{
kongxq[i].startaddr=s;
kongxq[i].size=len;
break;
}
}
}
if(t1==0)
{
for(i=0;i<6;i++)
{
if((kongxq[i].startaddr+kongxq[i].size==s)
&&(kongxq[i].flag==1))
{
kongxq[i].size+=len;
t3=1;
break;
}
if(t3==0)
for(j=0;j<6;j++)
if(kongxq[j].flag==0)
{
kongxq[j].startaddr=s;
kongxq[j].size=len;
kongxq[j].flag=1;
break;
}
}
}
}
void print()
{
int i;
printf("\n 起始地址 | 大小
|是否空闲 \n\n");
for(i=0;i<6;i++)
{
printf(" %3d | %3d |
%3d \n",
kongxq[i].startaddr,kongxq[i].size,kongx
q[i].flag);
}
printf("\n");
}
main()
{
int jobsize,start;
char end;
printf("\n 是否有作业请求空闲区?
Y or
N:
");
while(end=getchar()=='y')
{
printf("初始空闲区状态:
\n");
circle();
print();
printf("请输入请求空闲区的作业
大小:
");
scanf("%d",&jobsize);
start=allocate(jobsize);
circle();
printf("分配后空闲区状态:
\n");
print();
8
if(!
start)
printf("没有适合的空闲区大
print();
printf("是否有其他作业的请求?
Y
小!
\n");
or N:
");
else
end=getchar();
printf("作业起始地址:
}
%d\n",start);
return 0;
printf("作业大小:
%d\n",jobsize);
callback();
五、算法及运行结果及分析
1.运行结果:
首次适应算法
}
最佳适应算法
9
2.实验总结:
通过运行内存分配和回收模拟的程序对内存管理理解加深了,在动态分区管理方
式中,能灵活地根据作业需要,动态地为之分配内存空间,其中关键是分区分配算
法,一旦内存块使用完毕,可以回收给系统以分配给其他的作业使用。
10