1,在内存分配时,系统优先使用空闲区低端的空间
10240+102380=112640 从地址112460开始分配,由低端向高端增长。
例如:分配给作业1,作业长度20,==》起始地址:112620,长度20,标志1。
每次分配,从起始地址最大的结点开始查找是否有合适区域
2,首次适应算法
// Memory_V1.cpp : 定义控制台应用程序的入口点。
/* *Name:Memory_V1.cpp *Author:WangLin *Created On:2015/11/04 *Function:首次适应算法 可变式分区分配,模拟实现分区的分配和回收过程。 */
#include "stdafx.h"
# include<iostream>
using namespace std;
struct partition //分区结构体:起始地址+分区长度+标志
{
int addr;
int length;
int tag;
partition* next;
};
partition *empty=new partition; //空闲分区
partition *busy=new partition;//已分配区
//初始化函数
void init()
{
//空闲分区初始化,empty和busy始终指向首地址最大结点,即低端第一个结点
empty->addr=10240;
empty->length=102400;
empty->tag=1;//1表示可用
empty->next=NULL;
//已分配区初始化
busy->addr=0;
busy->length=0;
busy->tag=0;//0表示空闲
busy->next=NULL;
}
/* 分配主存 */
void distriMemory()
{
int pname,plength;
partition* temp=new partition;
cout<<"输入作业名(请输入数字):";
cin>>pname;
temp->tag=pname;
cout<<endl;
cout<<"输入作业所需长度xk:";
cin>>plength;
temp->length=plength;
//为新作业分配主存,在空闲区表中,寻找长度大于等于temp结点长度的结点
partition* q=new partition;
partition* p=new partition;
bool isfind=false;//标志是否找到可分配的区域
for(q=empty;;p=q,q=q->next)//p是q的前驱
{
if((q->tag==1)&&(q->length>=temp->length))
{
isfind=true;
temp->addr=(q->addr+q->length)-temp->length;//在已分配区表中创建分配结点,分配区域
q->length-=temp->length; //修改空闲区表长度
if(q->length==0)//长度为0,区域已经不可以再分配了,从空闲区表删除
{
if(q==empty)//删除首结点
empty=empty->next;
else
p->next=q->next;
}
break;
}
}
if(isfind)
{
//修改已分配区表,temp挂到busy队列中
for(q=busy;;p=q,q=q->next)//找到第1个addr<temp->addr的结点q,temp插在q前面
if(q->addr<temp->addr)break;
if(q==busy)
{
temp->next=busy;//先连
busy=temp;//后断
}
else
{
temp->next=q;//先连
p->next=temp;//后断
}
cout<<"内存已分配!"<<endl;
}
else
cout<<"找不到合适大小的区域,内存分配失败!"<<endl;
}
/* 回收主存:4种情况 */
void colletMemory()
{
int pname;
cout<<"输入要回收分区的作业名:";
cin>>pname;
//在已分配区表中,按作业名查找要回收的结点p,何时删除这个结点?
partition* q=new partition;
partition* bfp=new partition;//p的前驱
partition* p=new partition;
partition* m=new partition;
for(p=busy;p!=NULL;bfp=p,p=p->next)
{
if((p->tag==pname)&&(p->addr!=0)&&(p->length)!=0)
{
if(p==busy)
busy=busy->next;
else
bfp->next=p->next;
p->next=NULL;//从已分配区表中取下p结点
break;
}
}
if(p!=NULL)
{
//==============4种情况修改空闲表========================================
for(q=empty;;m=q,q=q->next)//寻找地址和p相邻的结点,m->addr>p->addr>q->addr
if((q->tag==1)&&(q->addr<p->addr))
break;
//case1回收区与插入点的前一个空闲分区F1相邻接,此时将两个分区合并() p和m相邻,修改m,删除p
if(((p->addr+p->length)==m->addr)&&((q->addr+q->length)!=p->addr))
{
m->length+=p->length;
m->addr-=p->length;
m->tag=1;
delete(p);
}
//case2回收区与插入点的后一个空闲分区F2相邻接,此时将两个分区合并,p和q相邻,修改p,删除q
else if(((q!=empty)&&(p->addr+p->length)!=m->addr)&&((q->addr+q->length)==p->addr))
{
q->length+=p->length;
q->tag=1;
delete(p);
}
//3)回收区与插入点的前,后两个空闲分区相邻接,此时将三个分区合并,m,p,q相邻,修改m,删除p,q
else if(((p->addr+p->length)==m->addr)&&((q->addr+q->length)==p->addr))
{
m->length+=(p->length+q->length);
m->addr-=(p->length+q->length);
m->next=q->next;
m->tag=1;
delete(p);
delete(q);
}
//4)回收区既不与F1相邻接,又不与F2相邻接,此时应为回收区单独建立一个新表项,p挂到空闲表区中m和q之间
else
{
p->tag=1;
if(q==empty)
{
if(((q->addr+q->length)==p->addr))
q->length+=p->length;
else
{
p->next=empty;
empty=p;
}
}
else
{
p->next=q;//先连
m->next=p;//后断
}
}
//================空闲表区修改完毕-===================
cout<<"内存已回收!"<<endl;
}
else
cout<<"作业不存在!"<<endl;
}
/*显示主存 (1)显示空闲分区表 empty (2)显示已分配表busy */
void dispMemory()
{
partition *p=new partition;
char ch;
p=empty;//(1)显示空闲分区表 empty
cout<<endl<<"+++++++++++++"<<endl<<"【输出空闲分区表】"<<endl;
cout<<"起始地址"<<" "<<"分区长度"<<" "<<"标志"<<endl;
while(p!=NULL)
{
cout<<p->addr<<" ";
cout<<p->length<<" ";
cout<<p->tag<<endl;
p=p->next;
}
p=busy;//(2)输出已分配区表 busy
cout<<endl<<"+++++++++++++"<<endl<<"【输出已分配区表】"<<endl;
cout<<"起始地址"<<" "<<"分区长度"<<" "<<"标志"<<endl;
while(p!=NULL)
{
cout<<p->addr<<" ";
cout<<p->length<<" ";
cout<<p->tag<<endl;
p=p->next;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
init();
bool stop_flag=true;//程序结束标志
int ch;
while(stop_flag)
{
cout<<endl<<"============================================================="<<endl;
cout<<"选择功能项<0-退出;1-分配主存;2-回收主存;3-显示主存>"<<endl;
cout<<"显示功能项<0-3>:";
cin>>ch;
switch (ch)
{
case 0:cout<<"程序已结束,再见!"<<endl;stop_flag=false;
break;
case 1:distriMemory();
break;
case 2:colletMemory();
break;
case 3:dispMemory();
break;
default:cout<<"输入有误,请重新输入"<<endl;
break;
}
}
return 0;
}
3 .最佳适应算法
/* 分配主存 */
void distriMemory()
{
int pname,plength;
partition* temp=new partition;
cout<<"输入作业名(请输入数字):";
cin>>pname;
temp->tag=pname;
cout<<endl;
cout<<"输入作业所需长度xk:";
cin>>plength;
temp->length=plength;
//为新作业分配主存,在空闲区表中,寻找长度大于等于temp结点长度的结点
partition* q=new partition;
partition* p=new partition;
//从全部空闲区中找出能满足作业需求的容量最小的空闲区分配之
q->length=MAXLENGTH;
partition* s=empty;
partition* ps=new partition;
while(s!=NULL)
{
if((s->tag==1)&&(s->length>=temp->length))
{
if(s->length<q->length)
{
p=ps;//p是q的前驱
q=s;
}
}
ps=s;//ps是s的前驱
s=s->next;
}
if(q->length!=MAXLENGTH)//如果找到可以分配的区域
{
temp->addr=(q->addr+q->length)-temp->length;//在已分配区表中创建分配结点,分配区域
q->length-=temp->length; //修改空闲区表长度
if(q->length==0)//长度为0,区域已经不可以再分配了,从空闲区表删除
{
if(q==empty)//删除首结点
empty=empty->next;
else
p->next=q->next;
}
//修改已分配区表,temp挂到busy队列中
for(q=busy;;p=q,q=q->next)//找到第1个addr<temp->addr的结点q,temp插在q前面
if(q->addr<temp->addr)break;
if(q==busy)
{
temp->next=busy;//先连
busy=temp;//后断
}
else
{
temp->next=q;//先连
p->next=temp;//后断
}
cout<<"内存已分配!"<<endl;
}
else
cout<<"找不到合适大小的区域,内存分配失败!"<<endl;
}