1.题目
动态分区式存贮区管理
设计一个动态分区式存贮区管理程序,要求支持不同的放置策略。如首次、最佳、最坏。
说明:
- (1)分区描述器rd如下:
flag size next
要求自由主存队列按链表组织。
主存大小假设为maxsize(单位为节=rd的大小)。 - (2)主程序结构如下:
输入放置策略
申请一块内存作为主存
循环处理用户的请求(包括申请、释放)
申请函数 Addr=Request(size)
释放函数 Release(addr) - (3)数据实例:maxsize=512
J1申请162,J2申请64,J3申请120,J4申请86,J1完成,J3完成,J5申请72,J6申请100,J2完成,J7申请36,J8申请60,J4完成,J9申请110,J10申请42。备注:
(a)所有大小其单位为节(1节=rd的大小)
(b)作业申请n节,实际分配的分区大小应为n+1节。 其中一节作为分区描述器,其他n节提供给作业。
(c)已分配区放在高地址处。
(d)合并时应考虑四种情况: 假设回收区为r,上邻为f1(f1需搜索自由主存队列),下邻为f2(f2可直接计算)A)f1空闲,f2已分配 ;B)f1已分配,f2空闲; C)f1空闲,f2空闲;D)f1已分配,f2已分配;
2.程序设计
声明基本的头文件,其中包括conio.h,使得程序可以使用getche(),输入后立即从控制台取字符,不以回车为结束(带回显)。然后就是定义一个分区描述器信息结构体,包含名字、地址、大小以及指向下一个分区描述器的指针next,然后就是定义一个空闲区队列和一个已分配队列。
接下来就是一个删除结点函数void Delete_node(node* p,node* q)//删除q结点 {p->next=q->next;free(q);}和一个将结点插入至已占用队列的函数void Insert_node
(nodep){p->next=occupy_list->next;occupy_list->next=p;},然后还有一个初始化结点函数node Initialize_node(node* p,int address=0,int size=0,string name="")、一个初始化两个队列、主存大小的函数以及还有一个比较简单的输出显示信息的函数,由于这几个函数比较简单,这里便不在介绍。
然后就是首次适应算法First_fit()函数:初始化两个结点node* current=free_list->next;node* previous=free_list;并设置进程是否分配内存成功标志flag,当队列不为空时,从低地址开始比较分区和进程的内存大小,若空闲分区的大则更新进程各个信息,并将flag设置为true,同时若更新后的空闲区队列的该区内存为0,则从空闲区队列删掉该区,同时将p插入已占用队列,break跳出循环;若不符合分配条件则current=current->next;previous=previous->next;继续查找符合条件的。然后利用flag判断是否分配成功,若成功则输入该进程信息,否则输出内存分配失败。
接下来是最佳适应法:同样的首先定义并初始化各个变量,然后利用循环寻找比进程所需内存大并且大小最小的分区,利用flag标志,找到则更新各个信息,并输出进程信息,否则输出分配失败。在该算法之后的最坏适应算法由于和该算法基本一样,只是在寻找条件if(present1->size>=p->size&&present1->size>=present2->size)不一样而已,所以这里便不再介绍。
然后就是回收内存算法:输入要回收的进程名并且定义并初始化各个变量,然后首先查找要回收的进程,接着分别按照回收进程前面无空闲区、回收进程后面无空闲区以及回收进程前后有空闲区(包括f1空闲,f2空闲或f1空闲,f2分配、f1分配,f2空闲、f1分配,f2分配三种情况),找到进程所在的区间并进行相应的操作即可,具体实现还得看程序。
后面就是Place函数,输出菜单利用switch选择何种空闲区放置策略,而后面的主函数也是输出菜单并利用switch调用相应的函数供执行何种操作,比如有1、重分配主存空间2、显示主存使用情况3、选择放置策略4、回收内存0、退出系统这些操作。
而我觉得这个程序比较好的地方是执行界面以及各逻辑操作之间的转换做得比较好,例如使用getche();//输入后立即从控制台取字符,不以回车为结束(带回显),使得界面操作起来更加顺畅一些;还有就是利用system(“cls”),清除残余的运行界面,使得更加查看容易查看相应的内容。
3.测试结果
4.源码
#include <iostream>
#include <conio.h>//使用getche(),输入后立即从控制台取字符,不以回车为结束(带回显)
#include <string>
using namespace std;
struct node
{
string name;
int address;
int size;
node* next;
};
node* free_list; //空闲区队列
node* occupy_list;//已分配队列
void Delete_node(node* p,node* q)//删除q结点
{
p->next=q->next;
free(q);
}
void Insert_node(node* p) //插入结点至已占用队列
{
p->next=occupy_list->next;
occupy_list->next=p;
}
node* Initialize_node(node* p,int address=0,int size=0,string name="")
{ //初始化结点
p->next=new node;
node* q=p->next;
q->name=name;
q->address=address;
q->size=size;
q->next=nullptr;
return q;
}
void Initialize_list() //初始化队列、主存大小
{
free_list=new node; //初始化空闲区队列
free_list->address=0;
free_list->size=0;
free_list->next=nullptr;
occupy_list=new node; //初始化已占用队列
occupy_list->address=0;
occupy_list->size=0;
occupy_list->next=nullptr;
cout<<"请输入主存大小: ";
int i;
cin>>i;
if(Initialize_node(free_list,0,i))
cout<<"初始化成功!\n";
else
cout<<"初始化失败!\n";
}
void Display() //显示信息
{
node *p=free_list->next; //输出空闲区队列
cout<<"未分配:\n";
if(p==nullptr)
cout<<"无\n";
else
{
while(p!=nullptr)
{
cout<<"起始位置:"<<p->address<<" 大小:"<<p->size;
cout<<endl;
p=p->next;
}
}
p=occupy_list->next; //输出占用区队列
cout<<"已分配:\n";
if(p==nullptr)
cout<<"无\n";
else
{
while(p!=nullptr)
{
cout<<"进程名:"<<p->name<<'\t';
cout<<"起始位置:"<<p->address<<'\t'<<" 大小:"<<p->size;
cout<<endl;
p=p->next;
}
}
}
void First_fit(node* p) //首次适应算法
{
node* current=free_list->next;
node* previous=free_list;
bool flag=false;
while(current!=nullptr)
{
if(current->size>=p->size)//寻找符合条件的分区
{
flag=true; //符合条件更新进程信息
current->size-=p->size;
p->address=current->address;
current->address+=p->size;
if(current->size==0)
Delete_node(previous,current);
Insert_node(p);
break;
}
current=current->next; //没找到继续查找
previous=previous->next;
}
if(flag) //分配成功则输出进程信息
{
cout<<"进程"<<p->name<<"地址分配成功! 地址:"<<p->address;
cout<<" 大小:"<<p->size;
cout<<endl;
}
else
{
cout<<"内存分配失败!\n";
}
}
void Best_fit(node* p) //最佳适应算法
{
node* present=free_list->next;//定义并初始化
node* previous=free_list;
node* best_present=present;
node* best_previous=previous;
bool flag=false;
while(present!=nullptr)
{
if(present->size>=p->size&&present->size<=best_present->size)
{ //寻找最佳分配内存
flag=true;
best_present=present;
best_previous=previous;
}
present=present->next;
previous=previous->next;
}
if(flag) //找到则更新信息
{
best_present->size-=p->size;
p->address=best_present->address;
best_present->address+=p->size;
if(best_present->size==0)
Delete_node(best_previous,best_present);//从空闲队列删除free_current
Insert_node(p); //在已占用队列插入p
cout<<"内存分配成功! 地址:"<<p->address<<endl;
}
else
cout<<"内存不足!分配失败!\n";
return;
}
void Worst_fit(node* p) //最坏适应算法
{
node* present=free_list->next; //定义并初始化
node* previous=free_list;
node* best_present=present;
node* best_previous=previous;
bool flag=false;
while(present!=nullptr)
{
if(present->size>=p->size&&present->size>=best_present->size)
{ //寻找最坏分配内存
flag=true;
best_present=present;
best_previous=previous;
}
present=present->next;
previous=previous->next;
}
if(flag) //找到则更新信息
{
best_present->size-=p->size;
p->address=best_present->address;
best_present->address+=p->size;
if(best_present->size==0)
Delete_node(best_previous,best_present);//从空闲队列删除free_current
Insert_node(p); //在已占用队列插入p
cout<<"内存分配成功! 地址:"<<p->address<<endl;
}
else
cout<<"内存不足!分配失败!\n";
return;
}
void Recycle() //回收内存
{
string process_name;
printf("请输入要回收的进程名: ");
cin>>process_name;
node* occupy_current=occupy_list->next;
node* occupy_previous=occupy_list;
bool flag=false;
while(occupy_current!=nullptr)
{
if(occupy_current->name==process_name)
{
flag=true; //找到要回收的进程
occupy_previous->next=occupy_current->next;//在已占用队列中删掉occupy_current(回收的进程)
node* free_current=free_list->next; //初始化
node* free_previous=free_list;
if(occupy_current->address+occupy_current->size<=free_current->address)
{ //回收进程前面无空闲区
occupy_current->next=free_previous->next;
free_previous->next=occupy_current;
return;
}
while(free_current!=nullptr)
{
if((free_previous->address+free_previous->size<=occupy_current->address)&&(occupy_current->address+occupy_current->size<=free_current->address))
{ //f1空闲,f2空闲或f1空闲,f2分配
if(free_previous->address+free_previous->size==occupy_current->address)
{
free_previous->size+=occupy_current->size;
if(free_previous->address+free_previous->size==free_current->address)
{
free_previous->size+=free_current->size;
Delete_node(free_previous,free_current);
}
}
else if(occupy_current->address+occupy_current->size==free_current->address)
{ //f1分配,f2空闲
free_current->address=occupy_current->address;
free_current->size+=occupy_current->size;
}
else
{
occupy_current->next=free_current;//f1分配,f2分配
free_previous->next=occupy_current;
}
return;
}
free_current=free_current->next;
free_previous=free_previous->next;
}
if(free_previous->address+free_previous->size<occupy_current->address)
{ //回收进程前面无空闲区
free_previous->next=occupy_current;
occupy_current->next=nullptr;
}
break;//找到所要回收的进程并已回收则退出循环,无需再继续查找
}
occupy_current=occupy_current->next;
occupy_previous=occupy_previous->next;
}
if(!flag)
cout<<"未找到该进程!内存回收失败!\n";
}
void Place() //选择放置策略并分配内存
{
node* p=new node;
int choice1;
p->next=nullptr;
cout<<"请输入进程名字:";
cin>>p->name;
cout<<"请输入进程大小:";
cin>>p->size;
cout<<endl;
cout<<"*****************************\n";
cout<<"* 空闲区放置策略 *\n";
cout<<"* *\n";
cout<<"* 1、首次适应算法 *\n";
cout<<"* 2、最佳适应算法 *\n";
cout<<"* 3、最坏适应算法 *\n";
cout<<"* *\n";
cout<<"*****************************\n";
cout<<"请输入您的指令:";
choice1=getche();
cout<<endl;
switch(choice1)
{
case '1':First_fit(p);break;
case '2':Best_fit(p); break;
case '3':Worst_fit(p);break;
}
}
int main(void)
{
int choice2;
cout<<"注意:本程序中分配的地址默认包括分区描述器大小1在内!\n\n";
Initialize_list();
while(1)
{
system("pause"); //按任意键继续
system("cls"); //清除屏幕
cout<<"\n*****************************************\n";
cout<<"* 动态分区式存贮区管理系统 *\n";
cout<<"* *\n";
cout<<"* 1、重分配主存空间 *\n";
cout<<"* 2、显示主存使用情况 *\n";
cout<<"* 3、选择放置策略 *\n";
cout<<"* 4、回收内存 *\n";
cout<<"* 0、退出系统 *\n";
cout<<"* *\n";
cout<<"*****************************************\n";
cout<<"请输入您的指令:";
choice2=getche();//输入后立即从控制台取字符,不以回车为结束(带回显)
cout<<endl;
switch(choice2)
{
case '1':Initialize_list();break;
case '2':Display(); break;
case '3':Place(); break;
case '4':Recycle(); break;
case '0':return 0;
default:
{
cout<<"错误指令!请重新输入!\n";
break;
}
}
}
}