实验四:内存分配算法
——动态分区方式主存的分配和回收
本机环境:macOS Big Sur
一、前言
一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请主存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实现是与主存储器的管理方式有关的,软件模拟内存的分配。
二、实验目的
通过本实验帮助学生理解在动态分区管理方式下应怎样实现主存空间的分配和回收。
三、实验内容
在动态分区管理方式下采用不同的分配算法实现主存分配和实现主存回收。
四、实验要求
- (1)可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离、主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。例如:
为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空区说明表,格式如下:
其中,起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲区的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来登记新的空闲区(例如,作业撤离后,它所占的区域就成了空闲区,应找一个“空表目”栏登记归还区的起址和长度且修改状态)。由于分区的个数不定,所以空闲区说明表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。
上述的这张说明表的登记情况是按提示(1)中的例所装入的三个作业占用的主存区域后填写的。 - (2)当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一个部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的“碎片”,在作业请求装入时,尽可能地利用主存的低地址部分的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。
- (3)采用首次适应算法或循环首次算法或最佳适应算法分配主存空间。由于本实验是模拟主存的分配,所以当把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。(即输出当时的空闲区说明表及其内存分配表)
- (4)当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。例如,在提示(1)中列举的情况下,如果作业2撤离,归还所占主存区域时,应与上、下相邻的空闲区一起合成一个大的空闲区登记在空闲区说明表中。
- (5)请按首次适应算法或循环首次算法或最佳适应算法设计主存分配和回收的程序。然后按(1)中假设主存中已装入三个作业,且形成两个空闲区,确定空闲说明表的初值。现有一个需要主存量为6K的作业4 申请装入主存;然后作业3 撤离;再作业2 撤离。请你为它们进行主存分配和回收,把空闲区
说明表的初值以及每次分配或回收后的变化显示出来或打印出来。
五、测试数据文件格式
打印程序运行时的初值和运行结果,要求如下:
- 打印空闲区说明表的初始状态,作业4 的申请量以及为作业4 分配后的空闲区说明表状态;
- 再依次打印作业3 和作业2 的归还量以及回收作业3,作业2 所占主存后的空闲区说明表。
六、源代码
#include <iostream>
#include <list>
#include <iomanip>
#include <string>
using namespace std;
struct Node{
int start;
int end;
bool occupied;
int size(){
return end-start;
}
void set(int start, int end, bool occupied=0){
this->start=start;
this->end=end;
this->occupied=occupied;
}
void printNode(){
cout<<"start:"<<start<<" end:"<<end<<" size:"<<this->size()<<endl;
}
Node(int start, int end, bool occupied=0){
this->start=start;
this->end=end;
this->occupied=occupied;
}
Node(){ }
};
bool request(list<Node>*, int, bool); //采用首次适应算法
bool release(list<Node>*, int);
void printList(list<Node>*);
void mergeList(list<Node>*);
//bool类型请求函数 如果请求成功会返回1
bool request(list<Node>* l, int need, bool flag_add){
if(l->size()==0) return 0;
for(list<Node>::iterator iter=l->begin(); iter!=l->end(); iter++){
if(iter->size() >= need && iter->occupied==0){
//如果找到了合适的位置 则将原iter处一分为二,在前半部分放need,occupied置一
if(flag_add == 1){
Node t_rest(iter->start, iter->start+need, 1); //采用首次适应算法 按顺序找到第一个可以用的
list<Node>::iterator iter1;
iter1 = l->insert(iter , t_rest);
iter->start = iter->start+need;
}
return 1;
}
}
return 0;
}
bool release(list<Node>* l, int index){
if(l->size()==0) return 0;
int i=0;
for(list<Node>::iterator iter=l->begin(); iter!=l->end(); iter++){
if(i==index && iter->occupied==1){
iter->occupied=0;
mergeList(l);
return 1;
}
else i++;
}
return 0;
}
//将连续的空区域合并
void mergeList(list<Node>* l){
if(l->size()<=1) return;
list<Node>::iterator foot1 = l->begin();
list<Node>::iterator foot2 = l->begin();
++foot2; //foot2指向第二个
while(true){
if(l->size()==1) break;
if(foot1->occupied==0 && foot2->occupied==0){
foot1->end += foot2->size();
if (foot2==l->end()){
l->pop_back();
break;
}
else if(foot2!=l->end()) foot2=l->erase(foot2);
else break;
}
else{
foot1++;
foot2++;
}
if(foot2 == l->end()) break;
}
}
//打印整个“内存”
void printList(list<Node>* l){
list<Node>::iterator iter = l->begin();
for(int i=0;i<l->size();i++){
cout<<"No."<<i<<" / ";
cout<<"start:"<<setw(4)<<iter->start<<" / end:"<<setw(4)<<iter->end<<" / used:"<<iter->occupied<<endl;
iter++;
}
}
int main(){
list<Node> M;
Node initialize_m(0,1024);
M.push_back(initialize_m);
cout<<"//Memory Management System//"<<endl;
cout<<"Memory size overall: 1024K"<<endl;
while(true){
cout<<"///"<<endl;
cout<<"PrintMemoryList:"<<endl;
printList(&M);
cout<<"Enter 1 to request memory..."<<endl;
cout<<"Enter 2 to release memory..."<<endl;
cout<<"Enter 0 to EXIT..."<<endl;
int i=0;
cin>>i;
if(i==0){
cout<<"MMS EXIT with Code 0"<<endl;
break;
}
else if(i==1){
cout<<"Enter memory size you request..."<<endl;
int need;
cin>>need;
if(request(&M, need, 1)) cout<<"SUCCEEDED!"<<endl;
else cout<<"FAILED!"<<endl<<endl;;
}
else if(i==2){
cout<<"Enter memory index you want to release..."<<endl;
int index;
cin>>index;
if(release(&M, index)) cout<<"SUCCEEDED!"<<endl;
else cout<<"FAILED!"<<endl<<endl;
}
else{
cout<<"MMS EXIT with Code -1"<<endl;
break;
}
cout<<"Press the ENTER key to continue..."<<endl;
getchar();
getchar();
}
}