//基于动态分区分配的存储器管理系统的设计与实现
#include <bits/stdc++.h>
using namespace std;
int N;//定义空闲分区最大值
//定义空闲分区
struct Block {
//分区id、开始地址、分区大小、使用状态(free/busy)、后继指针、前驱指针
int Block_id;
int Address_start,Block_size;
bool Use_state;
Block *next,*pre;
};
Block *head;//头节点
Block *tail;//尾节点
Block *last;//上次查找结束的节点位置,初始位置为head节点,循环首次算法中用到,定义为全局变量,创建空闲链表时首次指向head节点
//创建双向链表,头节点为空
void Create_list(){
head=new Block();
tail=new Block();
last=new Block();
head->next=tail;
head->pre=NULL;
tail->next=NULL;
tail->pre=head;
last=head;//创建空闲链表时首次指向head节点
tail->Block_id=0;
tail->Address_start=0;
tail->Block_size=N;
tail->Use_state=0;
}
//算法1首次适应算法
bool First_fit(int id,int request){
Block *memory=new Block();
memory->Block_id=id;
memory->Block_size=request;
memory->Use_state=1;
//创建memory节点并赋值,记录分配请求
Block *p=head->next;//每次从头开始扫描链表
while (p){
if (!p->Use_state){
//情况1空闲链表中存在大小与请求相等的分区
if (p->Block_size==request){
p->Block_id=id;
p->Use_state=1;//更新空闲链表
return true;
}
//情况2空闲链表中存在大小大于请求相等的分区
else if (p->Block_size>request){
memory->pre=p->pre;
p->pre->next=memory;
memory->next=p;
p->pre=memory;//参考文献,插入节点是前驱节点,需遵循从左往右原则,实现memory节点的插入
memory->Address_start=p->Address_start;
p->Address_start=memory->Address_start+memory->Block_size;//更新分区的首地址
memory->Use_state=1;//更新分区使用状态
p->Block_size-=request;//更新空闲分区的大小
return true;
}
}
p=p->next;//没有满足分配请求的分区大小则继续指针后移
}
return false;//遍历结束,未找到合适的空闲分区,分配请求失败
}
//算法2循环首次适应算法
bool Next_fit(int id,int request){
//使用循环链表
Block *memory=new Block();
memory->Block_id=id;
memory->Block_size=request;
memory->Use_state=1;
Block *p=last->next;
while (p!=last){
if (p->next==NULL)p->next=head->next;//循环链表,首尾相连
if (!p->Use_state){
if (p->Block_size==request){
p->Block_id=id;
p->Use_state=1;
last=p;//结束时更新last位置
return true;
}
else if (p->Block_size>request){
memory->pre=p->pre;
p->pre->next=memory;
memory->next=p;
p->pre=memory;//参考文献,插入节点是前驱节点,需遵循从左往右原则,实现memory节点的插入
memory->Address_start=p->Address_start;
p->Address_start+=request;//更新首地址
memory->Use_state=1;//更新分区使用状态
p->Block_size-=request;//更新last的大小
last=p;//更新index位置
return true;
}
}
p=p->next;//没有满足分配请求的分区大小则继续指针后移
}
return false;
}
//算法3最佳适应算法
bool Best_fit(int id,int request){
int minimum=0x3f3f3f3f;//记录大小合适的最小空闲分区块
Block *memory=new Block();
memory->Block_id=id;
memory->Block_size=request;
memory->Use_state=1;
Block *p=head->next;
Block *index=NULL;//记录找到的最小空闲分区的位置
int flag=0;//标记分区相等或大于的情况,1表示相等,2表示大于,0表示未找到合适空闲分区
while (p){
if (!p->Use_state){
if (p->Block_size==request){
p->Block_id=id;
p->Use_state=1;
index=p;//更新index位置
flag=1;
return true;
}
else if (p->Block_size>request){
if (p->Block_size<minimum){
minimum=p->Block_size;
index=p;//更新index位置
flag=2;
}
}
}
p=p->next;//指针后移,继续遍历空闲链表
}
if (!flag)return 0;//没有找到合适的空闲分区
else {
if (flag==2){
memory->pre=index->pre;
index->pre->next=memory;
memory->next=index;
index->pre=memory;//参考文献,插入节点是前驱节点,需遵循从左往右原则,实现memory节点的插入
memory->Address_start=index->Address_start;
index->Address_start+=request;//更新首地址
memory->Use_state=1;//更新分区使用状态
index->Block_size-=request;//更新index的大小
}
return true;
}
}
//算法4最坏适应算法
bool Worst_fit(int id,int request){
int maximum=-1;//记录大小合适的最大空闲分区块
Block *memory=new Block();
memory->Block_id=id;
memory->Block_size=request;
memory->Use_state=1;
Block *p=head->next;
Block *index=NULL;//记录找到的最大空闲分区的位置
int flag=0;//标记分区相等或大于的情况,1表示相等,2表示大于,0表示未找到合适空闲分区
while (p){
if (!p->Use_state){
if (p->Block_size==request){
p->Block_id=id;
p->Use_state=1;//更新空闲链表
flag=1;
return true;
}
else if (p->Block_size>request){
if (p->Block_size>maximum){
maximum=p->Block_size;
index=p;//更新index位置
flag=2;
}
}
}
p=p->next;//指针后移,继续遍历空闲链表
}
if (!flag)return false;//没有找到合适的空闲分区
else {
if (flag==2){
memory->pre=index->pre;
index->pre->next=memory;
memory->next=index;
index->pre=memory;//参考文献,插入节点是前驱节点,需遵循从左往右原则,实现memory节点的插入
memory->Address_start=index->Address_start;
index->Address_start+=request;//更新首地址
memory->Use_state=1;//更新分区使用状态
index->Block_size-=request;//更新index的大小
}
return true;
}
}
//操作1分配内存
bool Allocate(int choice,int id,int request){
if (request>0){
if (choice==1){
if (First_fit(id,request))return true;
else return false;
}else if (choice==2){
if (Next_fit(id,request))return true;
else return false;
}else if (choice==3){
if (Best_fit(id,request))return true;
else return false;
}else if (choice==4){
if (Worst_fit(id,request))return true;
else return false;
}
}else {
cout<<"分配大小无效,请重新输入!"<<"\n";
return false;
}
}
//操作2回收内存
void Recycle(int id){
Block *p=head->next;
while (p){
if (p->Block_id==id){
p->Block_id=0;
p->Use_state=0;
/*内存合并包括四种情况
1、空闲分区前后都没有空闲分区
2、仅有空闲分区前面有空闲分区
3、仅有空闲分区后面有空闲分区
4、空闲分区前后都有空闲分区
*/
//内存合并,当前面存在空闲分区时就进行合并
//当遇到前面是头节点或后面没有结点时这两种时,需进行特判
if (p->pre==head)continue;
else if (!p->pre->Use_state){
p->pre->Block_size+=p->Block_size;
p->pre->next=p->next;
p->next->pre=p->pre;
}
//内存合并,当后面有空闲分区时就进行合并
if (p->next==NULL)continue;
else if (!p->next->Use_state){
p->Block_size+=p->Block_size;
p->next->next->pre=p;
p->next=p->next->next;
}
break;
}
p=p->next;
}
}
//操作3查看当前内存分配情况
void View(){
cout<<"———当前内存分配情况———"<<"\n";
Block *p=head->next;
while (p){
cout<<"作业号:";
if (!p->Block_id)cout<<"Free"<<"\n";
else cout<<p->Block_id<<"\n";
cout<<"起始地址:"<<p->Address_start<<"\n";
cout<<"分区大小:"<<p->Block_size<<"\n";
cout<<"使用状态:";
if (!p->Use_state)cout<<"Free"<<"\n";
else cout<<"Busy"<<"\n";
cout<<"——————————————"<<"\n";
p=p->next;
}
}
//主函数
int main(){
while(1){
bool initial=true;//标记初始状态
cout<<"———基于动态分区分配的存储器管理系统———"<<"\n";
cout<<"| 退出系统请按0 |"<<"\n";
cout<<"| 本系统支持以下四种算法: |"<<"\n";
cout<<"| 1、首次适应算法 |"<<"\n";
cout<<"| 2、循环首次适应算法 |"<<"\n";
cout<<"| 3、最佳适应算法 |"<<"\n";
cout<<"| 4、最坏适应算法 |"<<"\n";
cout<<"——————————————————————"<<"\n";
cout<<"您好!当前您已进入分配算法选择模块!"<<"\n";
int choice;
while (1){
cout<<"请输入您选择的分配算法编号:";
cin>>choice;
cout<<"请输入初始空间大小:";
cin>>N;
cout<<"\n";
if (!choice){
cout<<"即将退出系统!"<<"\n";
return 0;
}
if (choice<0||choice>4){
cout<<"输入无效,请重新输入!"<<"\n";
continue;
}
else break;
}
if (initial){
Create_list();//创建链表
initial=false;
}
cout<<"分配算法选择完成!"<<"\n";
cout<<"———本系统支持以下4种操作:———"<<"\n";
cout<<"| 1、分配内存 |"<<"\n";
cout<<"| 2、回收内存 |"<<"\n";
cout<<"| 3、查看当前内存分配情况 |"<<"\n";
cout<<"| 0、结束操作 |"<<"\n";
cout<<"—————————————————"<<"\n";
cout<<"您好!当前您已进入操作选择模块!"<<"\n";
int operate;
while (1){
cout<<"请输入您选择的操作编号:";
cin>>operate;
if (!operate){
cout<<"操作结束!"<<"\n";
View();
break;
}else if (operate==1){
int id,request;//请求分配的作业号及分配内存的大小
cout<<"请输入作业号、请求分配的内存大小"<<"\n";
cin>>id>>request;
if (Allocate(choice,id,request)){
cout<<"分配成功!"<<"\n";
//数据永久保存,写入文件
fstream fs; //可输入输出
//指定文件打开方式
fs.open("D:\\DTFQFPsystem.txt", ios::out|ios::app);
//文件写入
fs<<"当前操作信息如下:"<<"所选算法:"<<choice<<" "<<"所选操作:"<<operate<<" "<<"作业号:"<<id<<" "<<"请求:"<<request<<"\n";
fs<<"当前内存信息如下:分配成功!"<<"\n";
Block *p=head->next;
while (p){
fs<<"作业号:";
if (!p->Block_id)fs<<"Free"<<" ";
else fs<<p->Block_id<<"\n";
fs<<"起始地址:"<<p->Address_start<<" ";
fs<<"分区大小:"<<p->Block_size<<" ";
fs<<"使用状态:";
if (!p->Use_state)fs<<"Free"<<"\n";
else fs<<"Busy"<<"\n";
p=p->next;
}
fs.close();
}
else {
cout<<"分配失败!"<<"\n";
//数据永久保存,写入文件
fstream fs; //可输入输出
//指定文件打开方式
fs.open("D:\\DTFQFPsystem.txt", ios::out|ios::app);
//文件写入
fs<<"当前操作信息如下:"<<"所选算法:"<<choice<<" "<<"所选操作:"<<operate<<" "<<"作业号:"<<id<<" "<<"请求:"<<request<<"\n";
fs<<"当前内存信息如下:分配失败!"<<"\n";
Block *p=head->next;
while (p){
fs<<"作业号:";
if (!p->Block_id)fs<<"Free"<<" ";
else fs<<p->Block_id<<"\n";
fs<<"起始地址:"<<p->Address_start<<" ";
fs<<"分区大小:"<<p->Block_size<<" ";
fs<<"使用状态:";
if (!p->Use_state)fs<<"Free"<<"\n";
else fs<<"Busy"<<"\n";
p=p->next;
}
fs.close();
}
View();
}else if (operate==2){
int id;
cout<<"请输入释放作业号:";
cin>>id;
Recycle(id);//回收内存
//数据永久保存,写入文件
fstream fs; //可输入输出
//指定文件打开方式
fs.open("D:\\DTFQFPsystem.txt", ios::out|ios::app);
//文件写入
fs<<"当前操作信息如下:"<<"所选算法:"<<choice<<" "<<"所选操作:"<<operate<<" "<<"作业号:"<<id<<"\n";
fs<<"当前内存信息如下:"<<"\n";
Block *p=head->next;
while (p){
fs<<"作业号:";
if (!p->Block_id)fs<<"Free"<<" ";
else fs<<p->Block_id<<" ";
fs<<"起始地址:"<<p->Address_start<<" ";
fs<<"分区大小:"<<p->Block_size<<" ";
fs<<"使用状态:";
if (!p->Use_state)fs<<"Free"<<"\n";
else fs<<"Busy"<<"\n";
p=p->next;
}
fs.close();
View();
}else if (operate==3){
View();//查看当前内存分配情况
}else {
cout<<"输入无效,请重新输入!"<<"\n";
continue;
}
}
}
return 0;
}