采用首次适应算法的动态分区分配模拟课程设计实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1 需求分析
1)本程序要求实现对内存的动态分配与回收的模拟,同时,在内存的分配时还必须使用首次适应算法,最后,还要显示内存块分配和回收后空闲内存分区链的情况。
2)要实现对作业的内存分配,首先要有一个对作业进行创建和分配内存的模块,其中,该模块在分配内存时要使用首次适应算法;要实现对内存的回收,要有一个内存回收的模块,其中,该模块在回收内存时要考虑内存回收的四种情况;最后,还要有一个能显示内存空闲分区链的情况的模块。
2 概要设计
1)首次适应算法的结构如图1:
图1 首次适应算法的结构图
2)数据结构:
struct Fq
{
int size,o,no;
Fq *before,*next;
};
其中,Fq表示结构体的名字(类型),size表示分区的可用空间大小,o表示该分区的状态(是否已分配),no表示该分区中的作业标志,*before表示该结点的向前指针,*next表示该结点的向后指针。
3)各种函数说明:
void alloc(int b,int no,Fq *p);
对作业no进行内存分配的功能函数;其中,参数b表示需求的内存大小,参数no表示作业的编号,参数*p表示空闲分区链的第一个非空结点的指针;
void free(Fq *c);
将地址为c的分区的内存回收;其中,参数*c表示要回收内存的结点;
void create(Fq *head);
创建新作业的子函数;其中,参数*head表示空闲分区链的链首指针;要配合函数alloc()使用;
void cha(Fq *head);
查看内存中的空闲分区链的子函数;其中,参数*head表示空闲分区链的链首指针;
void hui(Fq *head);
回收内存的子函数;其中,参数*head表示空闲分区链的链首指针;要配合函数free()使用;
3 运行环境
1)操作系统: Windows XP ( 32位 / DirectX 11 )
2)电脑: X86 兼容台式电脑
处理器: 英特尔 Pentium(奔腾) 双核 E5300 @ 2.60GHz
内存: 2 GB
4 开发工具和编程语言
1)开发工具:Visual C++ 6.0;
2)编程语言:C++语言;
5 详细设计
1)程序结构如图2:
图2 程序结构图
2)●主菜单模块:
void main()//主函数
{
Fq *head=new Fq;head->next=new Fq;
head->next->size=MAXSIZE;
head->next->o=0;
head->next->next=NULL;
int choice=0;
do
{
cout<<"请选择你要进行的操作:"<<endl;
cout<<"1、创建新作业 2、查看空闲分区链 3、回收内存空间 0、退出"<<endl;
cin>>choice;
switch(choice)
{
case 1: create(head);break;
case 2: cha(head);break;
case 3: hui(head);break;
case 0: break;
default: cout<<"输入错误!"<<endl;
}
}while(choice!=0);
}
●创建新作业模块:
void create(Fq *head)//创建作业子函数
{
Fq *p=head->next;p->before=head;
int no=0,b=0;
cout<<"请输入要创建的作业的编号:";cin>>no;
cout<<"请输入作业的需求空间大小:";cin>>b;
alloc(b,no,p);//此处调用功能函数alloc()
}
●查看空闲分区链模块:
void cha(Fq *head)//查看内存中的空闲分区链的子函数
{
Fq *p=head->next;p->before=head;
int i=0;
cout<<"空闲分区链的情况为:"<<endl;
while(p!=NULL)
{
if(p->o==0)
{
cout<<"空闲分区"<<++i<<" "<<p->size<<"K"<<endl;
}
p=p->next;
}
}
●回收内存空间模块:
void hui(Fq *head)//回收内存的子函数
{
Fq *p=head->next;p->before=head;
int no=0;
cout<<"请输入要回收内存的作业号:";cin>>no;
while(p!=NULL)
{
if(p->no==no)
{
free(p);//此处调用功能函数free()
cout<<"作业"<<no<<"的内存已回收!"<<endl;
return ;
}
else p=p->next;
}
}
●内存分配功能函数模块:
void alloc(int b,int no,Fq *p)//对作业no进行内存分配的子函数{
while(p!=NULL)
{
if(p->o==1) {p=p->next;}
else
{
if(p->size>b)
{
if(p->size-b<=min_size)
{
p->o=1;p->no=no;
}
else
{
Fq *q=new Fq;Fq *r;
r=p->before;
r->next=q;q->before=r;
q->next=p;p->before=q;
q->size=b;
p->size=p->size-b;
q->no=no;
q->o=1;
}
cout<<"内存分配成功!"<<endl;
return ;
}
else p=p->next;
}
}
cout<<"内存分配失败!"<<endl;
}
●内存回收功能函数模块:
void free(Fq *c)//将地址为c的分区内存回收
{
if(c->before->o==0&&c->next->o==0)
{
Fq *r=c->before,*s=c->next->next;
r->size=(r->size+c->size+c->next->size);
r->next=s;
if(s!=NULL) s->before=r;
}
if(c->before->o==0&&c->next->o!=0)
{
c->before->size=c->before->size+c->size;
c->before->next=c->next;c->next->before=c->before;
}
if(c->next->o==0&&c->before->o!=0)
{
Fq *r=c->next->next;
c->size=c->size+c->next->size;
c->next=c->next->next;
if(r!=NULL) r->before=c;
c->o=0;
}
else c->o=0;
}
6 调试分析
1)内存分配功能函数模块:刚开始对作业分配内存时,只是将空闲分区的大小以及前后向指针进行修改,而没有对分配给作业的内存进行设置;这样,尽管内存的空闲分区大小已经变小,但是,以后却无法对已分配的内存空间以及作业进行修改;于是,我经过思考后,决定将分配给作业的内存空间也设置为一个分区,只不过不是空闲的分区,通过状态标识符o来与空闲分区进行区别。
2)回收内存空间模块:刚开始编写此模块的代码时,我有一种无从下手的感觉;因为,如果要回收某个作业的内存,那么必须知道该作业所在的内存中的位置;但是,刚开始我用的数据结构中只有表示内存状态的属性(分区可用空间大小,状态标识符,前后向指针),这样就不能对特定的作业进行操作;最后,我经过思考决定在内存的数据结构中增加一项,即作业标识符,用来保存分区中的作业信息,从而达到查找特定作业所在内存分区的目的。
3)在编写代码的过程中,我还遇到了一些小的问题;比如,对链表进行操作时,老是出现错误,不能对链表进行正确的操作等;这些问题与我对链表的认识不够深入和准确有关,不过,通过这次程序的编写,进一步加深了我对链表的理解,对链表的运用也变得得心应手了。
7 测试结果
1)测试数据:
作业1申请130KB;作业2申请60KB;作业3申请100KB;作业2释放60KB;
作业4申请200 KB;作业3释放100 KB;作业1释放130 KB;作业5申请140 KB;作业6申请60 KB;作业7申请50KB;作业6释放60 KB
2)程序运行结果如图3、4所示:
图3 程序运行结果图
图4 程序运行结果图。