目录
1.需求分析
2.代码实现
3.测试用例
4.总结与收获
1.需求分析
动态分区分配又称为可变分区分配,他是根据进程的实际需要,动态地为之分配内存空间。在实现动态分区分配时,将涉及到分区分配中所有的数据结构、分区算法和分区的分配与回收操作这三方面的问题。 在本实验中运用了四种分配算法,分别是首次适应算法,循环首次适应算法,最坏适应算法,最佳适应算法。
- 首次适应算法
FF算法要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始顺序查找,直到找到一个大小能满足要求的空闲分区为止。然后再按照作业的大小,从该分区划分出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。如果从链首直至链尾都不能找到一个能满足要求的分区,则表明系统中已经没有足够大的内存分配给该进程,内存分配失败,返回。
2.循环首次适应算法
NF(next fit)算法在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个K线分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块与请求大小相等的内存框架分配给该作业。
3.最佳适应算法
BF(best fit)算法要求将所有的空闲分区按照其容量以从小到大的顺序形成一空闲分区链。这样第一次找到的能满足要求的空闲区是最佳的。所谓“最佳”是指每次为作业分配内存时,只是把能满足要求又是最小的空闲分区分配给作业。
4.最坏适应算法
WF(worst fit)算法在扫描整个空闲分区表或链表时,只是挑选一个最大的空闲区,从中分割一部分存储空间给作业使用以至于存储器中缺乏大的空闲分区。
2.代码实现
C++代码:
#include<iostream>
#include<vector>
#include <iomanip>
#include <algorithm>
using namespace std;
class Partion
{
private:
int size;
int startaddress;
int endaddress;
bool flag;//是否空闲(1表示空闲)
int sort = 1;
public:
Partion(int psize, int paddress = 0) :size(psize)
{
flag = 1;
}
operator int() const
{
if (sort == 1)
{
return size;
}
else
{
return startaddress;
}
}
int& Size()
{
return size;
}
const int& Size()const
{
return size;
}
int& Startaddress()
{
return startaddress;
}
const int& Startaddress()const
{
return startaddress;
}
int& Endaddress()
{
return endaddress;
}
const int& Endaddress()const
{
return endaddress;
}
bool& Flag()
{
return flag;
}
const bool& Flag()const
{
return flag;
}
int& Tag()
{
return sort;
}
const int& Tag()const
{
return sort;
}
};
class Manage
{
private:
vector<Partion> PartionList;
public:
void Init(Partion& val)
{
//列表中第一个元素存放地址空间的总大小,以后不做处理
val.Startaddress() = 0;
val.Endaddress() = val.Size() + val.Startaddress();
PartionList.push_back(val);
PartionList.push_back(val);
}
void RecySpace(int space)//回收空间
{
int length = PartionList.size();
bool success = 0;
for (int i = 1; i < length; i++)
{
if (PartionList[i].Size() == space)
{
PartionList[i].Flag() = 1;
cout << "释放空间成功!" << endl;
break;
}
if (i == length + 1)
{
cout << "释放空间失败!" << endl;
}
}
}
void Base_FFNF(Partion process,int i)
{
cout << "成功分配空间!" << endl;
int size = PartionList[i].Endaddress() - process.Size() - PartionList[i].Startaddress();
int end = PartionList[i].Endaddress();
PartionList[i].Flag() = 0;
PartionList[i].Size() = process.Size();
PartionList[i].Endaddress() = PartionList[i].Size() + PartionList[i].Startaddress();
Partion Changeprocess(size);
PartionList.insert(PartionList.begin() + i + 1, Changeprocess);
PartionList[i + 1].Startaddress() = PartionList[i].Endaddress();
PartionList[i + 1].Endaddress() = end;
}
int NF(Partion process, int& next)
{
//当有进程要分配空间时,先看是否有足够的空闲分区
int i = next;
int length = PartionList.size();
bool success = 0;//
for (; i < length; )//跳过0
{
if (i == 0)//对列中存放的是空间的初始大小,不做处理,所以要跳过
{
i++;
}
//有足够大的空闲分区
if (process.Size() <= PartionList[i].Size() && PartionList[i].Flag())
{
success = 1;
//要分配给进程分区
cout << "成功分配空间!" << endl;
Base_FFNF(process,i);
break;
}
i = (i + 1) % length;
if (i == next)
{
cout << "分配空间失败!" << endl;
break;
}
}
next = next + 1;//下次查找的空闲分区
return next;
}
void FF(Partion process)
{
//当有进程要分配空间时,先看是否有足够的空闲分区
int length = PartionList.size();
bool success = 0;//
for (int i = 1; i < length; i++)
{
//有足够大的空闲分区
if (process.Size() <= PartionList[i].Size() && PartionList[i].Flag())
{
success = 1;
//要分配给进程分区
Base_FFNF(process, i);
break;
}
if (i == length + 1)
{
cout << "分配空间失败!" << endl;
break;
}
}
}
void BF(Partion process)
{
//按照空闲区大小从小到大排序
sort(PartionList.begin() + 1, PartionList.end());
FF(process);
}
void WF(Partion process)
{
//按照空闲区大小从大到小排序
sort(PartionList.begin() + 1, PartionList.end(),greater<Partion>());
FF(process);
}
void Print()
{
int length = PartionList.size();
for (int i = 0; i < length; i++)
{
PartionList[i].Tag() = 2;
}
sort(PartionList.begin() + 1, PartionList.end());
cout << "空间地址" << PartionList[0].Startaddress() << "----->" << PartionList[0].Endaddress() << endl;
cout << setw(18) << "开始地址" << setw(9) << "大小" << setw(13) << "结束地址" << setw(13) << "分配状态" << endl;
for (int i = 1; i < length; i++)
{
if (PartionList[i].Size() != 0)
{
cout << "第" << i << "个" << "分区:";
cout << setw(2) << PartionList[i].Startaddress() << setw(12) << PartionList[i].Size()
<< setw(13) << PartionList[i].Endaddress() << setw(13);
if (PartionList[i].Flag())
{
cout << "空闲" << endl;
}
else
{
cout << "已分配" << endl;
}
}
}
}
void Clear()
{
PartionList.clear();
}
void Menu()
{
cout << "1------首次适应算法------" << endl;
cout << "2------循环首次适应-------" << endl;
cout << "3------最佳适应算法--------" << endl;
cout << "4------最坏适应算法--------" << endl;
cout << "5------回收分区------" << endl;
}
};
int main()
{
Manage process;
int next = 1;//记录循坏首次适应算法的空闲标记
int size;
int space;
cout << "请输入分区块的总大小:";
cin >> size;
Partion init(size);
process.Init(init);
process.Menu();
int choose = 0;
char end = 'y';
while ('y' == end || 'Y' == end)
{
fflush(stdin);
cout << "请输入你的选择:";
cin >> choose;
if (choose < 1 || choose>5)
{
cout << "请重新输入!!!" << endl;
}
else if (choose == 5)
{
cout << "请输入释放空间的大小:";
cin >> space;
process.RecySpace(space);
process.Print();
}
else
{
cout << "请输入分配分区的大小:";
cin >> size;
Partion obj1(size);
switch (choose)
{
case 1:
process.FF(obj1);
process.Print();
break;
case 2:
process.NF(obj1, next);
process.Print();
break;
case 3:
process.BF(obj1);
process.Print();
break;
case 4:
process.WF(obj1);
process.Print();
break;
default:
cout << "请输入正确选项!!!" << endl;
break;
}
cout << "是否继续选择算法(Y/y):";
fflush(stdin);
cin >> end;
}
}
}
3.测试用例
-
- FF算法
分别给内存分配300K,100K,释放300K,分配150K的状态变化
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 已分配 |
2 | 300 | 212 | 未分配 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 已分配 |
2 | 300 | 100 | 已分配 |
3 | 400 | 121 | 未分配 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 未分配 |
2 | 300 | 100 | 已分配 |
3 | 400 | 121 | 未分配 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 150 | 已分配 |
2 | 150 | 150 | 空闲 |
3 | 300 | 100 | 已分配 |
4 | 400 | 121 | 未分配 |
- NF算法
分别给内存分配300K,100K,释放300K,分配150K的状态变化.
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 已分配 |
2 | 300 | 212 | 空闲 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 已分配 |
2 | 300 | 100 | 已分配 |
3 | 400 | 111 | 空闲 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 300 | 空闲 |
2 | 300 | 100 | 已分配 |
3 | 400 | 111 | 空闲 |
分区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 150 | 已分配 |
2 | 150 | 150 | 空闲 |
3 | 300 | 100 | 已分配 |
4 | 400 | 111 | 空闲 |
- BF算法
当系统中空闲分区如下表时,分别分配100K,30K大小的内存空间。
①未分配前状态:
区号 | 分区首地址 | 大小 | 状态 |
1 | 0 | 20 | 已分配 |
2 | 20 | 32 | 空闲 |
3 | 52 | 8 | 空闲 |
4 | 60 | 120 | 空闲 |
5 | 180 | 331 | 空闲 |
-
-
-
-
-
- 分配100K的分区状态表
区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 20 | 已分配 |
2 | 20 | 32 | 空闲 |
3 | 52 | 8 | 空闲 |
4 | 60 | 100 | 已分配 |
5 | 160 | 20 | 空闲 |
6 | 180 | 331 | 空闲 |
区号 | 起始地址 | 大小 | 状态 |
1 | 0 | 20 | 已分配 |
2 | 20 | 30 | 已分配 |
3 | 50 | 2 | 空闲 |
4 | 52 | 8 | 空闲 |
5 | 60 | 100 | 已分配 |
6 | 160 | 20 | 空闲 |
7 | 180 | 331 | 空闲 |
4.总结与收获
FF算法保留了高地址的大空闲块,但是也会增加查找分区时的开销,NF算法中设置起始查询指针是十分关键的,他减少了查找空闲分区的开销,但是也会造成大的空闲分区缺乏的情况,BF算法是按照存储区空闲区从小到大进行排序的,在存储器中留下了许多难以利用的碎片,而WF算法正好相反,是按照存储器空闲区从大到小的顺序来排列的,效率很高。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)