1. 问题描述
1.1 动态分区式存贮区管理
(1) 首次适应算法
首次适应算法是将输入的作业放置到主存里第一个足够装入它的地址最低的空闲区中,尽可能地利用存储器中低地址的空闲区,而尽量保存高地址的空闲区。
(2) 最佳适应算法
最佳适应算法是将输入的作业放置到主存中与它所需大小最接近的空闲区中,尽可能地利用存储器中小的空闲区,而尽量保存大的空闲区。
(3) 最坏适应算法
最坏适应算法是将输入的作业放置到主存中与它所需大小差距最大的空闲区中,尽可能地利用存储器中大的空闲区。
1.2 题目要求
设计一个动态分区式存贮区管理程序,要求支持不同的放置策略。如首次、最佳、最坏。
说明:
- 分区描述器rd如下:
flag size next
要求空闲区队列按链表组织。
主存大小假设为maxsize(单位为节=rd的大小)。 - 主程序结构如下:
输入放置策略
申请一块内存作为主存
循环处理用户的请求(包括申请、释放)
需设计两个函数处理用户请求:
申请函数 Addr=Request(size)
释放函数 Release(addr)
1.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.实现思路
2.1 文件读取
2.2 分区描述器
_flag代表该区域是否有空闲,true代表有,false代表没有。_belong代表分区域所属的进程,方便后续释放的操作,_size代表该区域大小。
2.3 申请
对于首次适应法,遍历描述器链表,若该区域是空闲的,即_flag == true,并且其大小能够满足当前请求的内存,则分两种情况。一是空闲大小正好等于申请的大小,这时只需将该区域描述器的_flag置为false,即该空闲被申请,_belong设置为该进程名。二是空闲大小大于申请的大小,则需要在该区域描述器之后新插入新的节点,其大小为要申请的内存,并且将空闲节点的_size减掉申请的内存,代表已被该进程申请。若所有空闲节点均不满足申请的内存,告知用户内存不足。
对于最优适应法,每次处理请求时,先将整个区域描述器的链表遍历,记录下该请求与链表中_size差值最小的节点,将该节点_size减去请求申请的内存。处理请求时链表中节点的变化以及请求不满足时的情况与首次适应法相同。
对于最差适应法,与最优适应法类似,只不过在遍历链表时,记录的是该请求与链表中_size差值最大的节点。
2.4 释放
释放资源时,分为6种情况。
(1) 被释放的内存为链表头
此时分两种情况,一是其下邻空闲区,则将该空闲区_size加上被释放的大小,删去头结点。二是下邻分配区,此时直接将空闲区_flag置为true,代表该区域资源已释放。
(2) 被释放的内存为链表尾
此时也分两种情况,一是其上邻空闲区,则将该空闲区_size加上被释放的大小,删去尾结点。二是上邻分配区,此时直接将空闲区_flag置为true,代表该区域资源已释放。
(3) 上邻空闲区
空闲区_size直接加上被释放的资源大小,删去该节点。
(4) 下邻空闲区
空闲区_size直接加上被释放的资源大小,删去该节点。
(5) 上下邻空闲区
上空闲区_size加上释放的资源和下空闲区的_size,删去该节点及下空闲区节点。
(6) 上下邻已分配区
直接将该节点的_flag置为true,代表该区域已空闲。
3. 核心代码
3.1 首次适应法
void first(PD pd) {
int cnt = -1;
for (auto& p : pdlist) {
cnt++;
if (p._flag == false)
continue;
if (p._size < pd._size)
continue;
if (p._size == pd._size) {
p._flag = false;
p._belong = pd._belong;
break;
}
else {
auto it = pdlist.begin();
advance(it, cnt + 1);
p._size -= pd._size;
pdlist.insert(it, pd);
output();
cout << endl;
break;
}
}
if (cnt == pdlist.size() - 1) {
cout << "cannot allocate memory for " << pd._belong << endl;
return;
}
}
3.2 最好适应法
void best(PD pd) {
int minDist = 99999;
int cnt = -1, where = 0;
for (auto p : pdlist) {
cnt++;
if (p._flag == true && p._size == pd._size) {
p._flag = false;
p._belong = pd._belong;
output();
return;
}
else if (p._flag == true && p._size > pd._size) {
if (p._size - pd._size < minDist) {
minDist = p._size - pd._size;
where = cnt;
}
}
}
auto it = pdlist.begin();
advance(it, where);
(*it)._size -= pd._size;
pdlist.insert(++it, pd);
output();
if (cnt == pdlist.size() - 1) {
cout << "cannot allocate memory for " << pd._belong << endl;
return;
}
}
3.3 最差适应法
void worst(PD pd) {
int maxDist = -99999;
int cnt = -1, where = 0;
for (auto p : pdlist) {
cnt++;
if (p._flag == true && p._size >= pd._size) {
if (p._size - (pd._size) > maxDist) {
maxDist = p._size - (pd._size);
where = cnt;
}
}
}
auto it = pdlist.begin();
advance(it, where);
(*it)._size -= pd._size;
pdlist.insert(++it, pd);
output();
if (cnt == pdlist.size() - 1) {
cout << "cannot allocate memory for " << pd._belong << endl;
return;
}
}
3.4 释放
void release(string belong) {
int cnt = -1;
for (auto it = pdlist.begin(); it != pdlist.end(); ++it) {
cnt++;
if ((*it)._belong != belong)
continue;
// 首个
if (cnt == 0) {
auto below = it;
below++;
// below空闲
if ((*below)._flag == false) {
(*below)._size += (*it)._size;
pdlist.erase(it);
}
// below已分配
else {
(*it)._flag = true;
(*it)._belong = "";
}
break;
}
// 最后一个
else if (cnt == pdlist.size() - 1){
auto above = it;
above--;
// above空闲
if ((*above)._flag == true) {
cout << "a" << endl;
(*above)._size += (*it)._size;
pdlist.erase(it);
}
// above已分配
else {
(*it)._flag = true;
(*it)._belong = "";
}
break;
}
// 其他
else {
auto below = it;
below++;
auto above = it;
above--;
// A) f1空闲,f2已分配;
if ((*above)._flag == true && (*below)._flag == false) {
(*above)._size += (*it)._size;
pdlist.erase(it);
}
// B) f1已分配,f2空闲;
else if ((*above)._flag == false && (*below)._flag == true) {
(*below)._size += (*it)._size;
pdlist.erase(it);
}
// C) f1空闲,f2空闲;
else if ((*above)._flag == true && (*below)._flag == true) {
(*above)._size += (*it)._size + (*below)._size;
pdlist.erase(it);
auto it2 = pdlist.begin();
advance(it2, cnt);
pdlist.erase(it2);
}
// D) f1已分配,f2已分配;
else if ((*above)._flag == false && (*below)._flag == false) {
(*it)._flag = true;
(*it)._belong = "";
}
break;
}
}
if (cnt == pdlist.size()) {
cout << "cannot release " << belong << endl;
return;
}
}
4.运行结果
J1分配:
J4完成:
首次适应结果:
最佳适应结果:
最差适应结果: