操作系统实验二——分区式存储管理
实验内容
设计程序模拟内存的动态分区法存储管理。内存空闲区使用自由链管理,采用最坏适应算法从自由链中寻找空闲区进行分配,内存回收时假定不做与相邻空闲区的合并。假定系统的内存共 640K ,初始状态为操作系统本身占用 64K 。在 tl 时间之后,有作业 A 、 B 、 c 、D 分别请求 8K 、 16K 、 64K 、 124K 的内存空间;在 t2 时间之后,作业 c 完成;在 t3 时间之后,作业E 请求 50K 的内存空间;在 t4 时间之后,作业 D 完成。要求编程序分别输出 tl 、 t2 、 t3 、 t4 时刻内存的空闲区的状态。
注意
如果遇到在visual stdio编译报错,报错内容是std::至少需要c++17。请查询如何修改编译器C++编译版本
时隔多日有同学向我反馈using iterator_deque = std::_Deque_iterator<std::pair<int, int>, std::pair<int, int> &, std::pair<int, int> *>;
在visualStudio报错问题,由于我使用的是CLion。查了一下在visualStudio应该写成using iterator_deque = std::deque<std::pair<int, int>>::iterator;
实现步骤
设置一个busyLink
struct busyLink {
char name;
int len;
int address;
// 三个适用于不同情形的构造函数
busyLink() : name('\0'), len(0), address(0) {}
busyLink(char _name) : name(_name), len(0), address(0) {}
busyLink(char _name, int _len, int _address)
: name(_name), len(_len), address(_address) {}
};
using busyNode = struct busyLink;
实现一个WF类,包含必要的两个类成员,以及一个记录剩余内存空间的变量
其中free_que空闲分区链中每一个结点,是一个包含长度和起始地址的对(pair)
private:
//包含#include <deque>头文件
using ilen = int;
using iaddres = int;
std::deque<std::pair<ilen, iaddres>> *free_que; // 空闲分区链表
std::deque<busyNode> *busy_que; // 内存占用区链表 结点内容为busyNode
int All_Memory = 640; // 给定系统的内存共640K
利用构造函数初始化两个队列
// 初始化两个队列
public:
// 利用构造函数 初始化成员
WF() {
busy_que = new std::deque<busyNode>();
free_que = new std::deque<std::pair<ilen, iaddres>>();
// 内存占用区 初始为OS本身所占用的64K内存 起始地址为0
busy_que->emplace_front(busyNode{'S', 64, 0});
// 初始空闲区
free_que->emplace_front(std::pair<int, int>{All_Memory - 64, 64});
All_Memory -= 64;
}
实现类成员函数,模拟分配内存
在分配之前,对空闲分区进行从大到小的排序,使第一块分区永远是最大的一块分区
// 模拟分配内存 参数作业名 请求长度
inline void requireMemo(char name, int require_len) {
// 对空闲分区排序
std::sort(free_que->begin(), free_que->end(),
[=](std::pair<int, int> a, std::pair<ilen, iaddres> b) {
return a.first > b.first;
});
//
if (free_que->front().first >= require_len) { // 有足够的空闲分区
busyNode new_node = busyNode(name);
new_node.address = busy_que->back().len + busy_que->back().address;
new_node.len = require_len;
busy_que->push_back(new_node);
All_Memory -= require_len;
//更新free_que
free_que->front().first = All_Memory;
free_que->front().second = busy_que->back().len + busy_que->back().address;
} else {
std::cout << "Can't allocation!";
exit(EXIT_FAILURE);
}
}
实现类成员函数,模拟内存回收
// 模拟内存回收
public:
inline void freeMemo(char name) {
for (auto it = busy_que->begin(); it != busy_que->end(); ++it) {
if (it->name == name) { // 找到要被回收的作业名
// 在空闲分区中新增被回收的内存空间
free_que->emplace_back(std::pair<int, int>{it->len, it->address});
// 删除
busy_que->erase(it);
break;
}
}
}
实现类成员函数,对相邻的空闲分区进行合并
:作业A和作业B相邻,就是说作业A的起始地址+作业A的长度等于作业B的起始地址
public:
// 将空闲分区相邻的内存进行合并
inline void MergerFreeMemo() {
// 对空闲分区排序
std::sort(free_que->begin(), free_que->end());
if (free_que->size() <= 1) return;
for (int i = 1; i < free_que->size(); ++i) {
if ((free_que->begin() + i)->second ==
(free_que->begin() + i - 1)->second + (free_que->begin() + i - 1)->first) {
//如果当前内存的起始地址 是上一个的起始地址+长度之和 说明它们相邻
Merge(free_que->begin() + i - 1, free_que->begin() + i);
}
}
}
protected:
using iterator_deque = std::_Deque_iterator<std::pair<int, int>,
std::pair<int, int> &, std::pair<int, int> *>;
// 对两个内存两块进行合并 参数是迭代器
inline void Merge(iterator_deque m1, iterator_deque m2) {
m1->first += m2->first;
free_que->erase(m2);
}
完整代码
#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
// 声明别名
using ilen = int;
using iaddres = int;
using iterator_deque = std::_Deque_iterator<std::pair<int, int>,
std::pair<int, int> &, std::pair<int, int> *>;
// 模拟时间点
enum Time {
t1, t2, t3
};
struct busyLink {
char name;
int len;
int address;
busyLink() : name('\0'), len(0), address(0) {}
busyLink(char _name) : name(_name), len(0), address(0) {}
busyLink(char _name, int _len, int _address)
: name(_name), len(_len), address(_address) {}
};
using busyNode = struct busyLink;
// Worst Fit 最坏适应动态分区匹配算法
class WF {
public:
// 利用构造函数 初始化成员
WF() {
busy_que = new std::deque<busyNode>();
free_que = new std::deque<std::pair<ilen, iaddres>>();
// 内存占用区 初始为OS本身所占用的64K内存 起始地址为0
busy_que->emplace_front(busyNode{'S', 64, 0});
// 初始空闲区
free_que->emplace_front(std::pair<int, int>{All_Memory - 64, 64});
All_Memory -= 64;
}
inline void past(int time) {
printf("时间%d", time);
}
// 模拟分配内存 参数作业名 请求长度
inline void requireMemo(char name, int require_len) {
// 对空闲分区排序
std::sort(free_que->begin(), free_que->end(),
[=](std::pair<int, int> a, std::pair<ilen, iaddres> b) {
return a.first > b.first;
});
if (free_que->front().first >= require_len) { // 有足够的空闲分区
busyNode new_node = busyNode(name);
new_node.address = busy_que->back().len + busy_que->back().address;
new_node.len = require_len;
busy_que->push_back(new_node);
All_Memory -= require_len;
//更新free_que
free_que->front().first = All_Memory;
free_que->front().second = busy_que->back().len + busy_que->back().address;
} else {
std::cout << "Can't allocation!";
exit(EXIT_FAILURE);
}
}
// 模拟内存回收
inline void freeMemo(char name) {
for (auto it = busy_que->begin(); it != busy_que->end(); ++it) {
if (it->name == name) {
free_que->emplace_back(std::pair<int, int>{it->len, it->address});
busy_que->erase(it);
break;
}
}
}
inline void print() const {
printf("内存占用区为:\n");
printf("作业名\t起始地址\t长度\n");
for (auto it = busy_que->begin(); it != busy_que->end(); ++it) {
printf("%c\t\t%d\t\t%d\n", it->name, it->address, it->len);
}
printf("内存空间区为:\n");
printf("起始地址\t大小\n");
for (auto it = free_que->begin(); it != free_que->end(); ++it) {
printf("%d\t\t%d\n", it->second, it->first);
}
printf("--------------------------------------\n");
}
// 将空闲分区相邻的内存进行合并
inline void MergerFreeMemo() {
// 对空闲分区排序
std::sort(free_que->begin(), free_que->end());
if (free_que->size() <= 1) return;
for (int i = 1; i < free_que->size(); ++i) {
if ((free_que->begin() + i)->second ==
(free_que->begin() + i - 1)->second + (free_que->begin() + i - 1)->first) {
//如果当前内存的起始地址 是上一个的起始地址+长度之和 说明它们相邻
Merge(free_que->begin() + i - 1, free_que->begin() + i);
}
}
}
~WF() = default;
protected:
// 对两个内存两块进行合并 参数是迭代器
inline void Merge(iterator_deque m1, iterator_deque m2) {
m1->first += m2->first;
free_que->erase(m2);
}
private:
std::deque<std::pair<ilen, iaddres>> *free_que; // 空闲分区链表 其中每一个结点{包含分区长度(first),分区起始地址(second)}
std::deque<busyNode> *busy_que; // 内存占用区链表 结点内容为busyNode定义在第7行
int All_Memory = 640; // 给定系统的内存共640K
};
int main() {
WF wf;
wf.past(t1);
wf.requireMemo('A', 8);
wf.requireMemo('B', 16);
wf.requireMemo('C', 64);
wf.requireMemo('D', 124);
wf.print();
wf.past(t2);
wf.freeMemo('C');
wf.print();
wf.past(t3);
wf.requireMemo('E', 50);
wf.print();
wf.freeMemo('D');
wf.print();
std::cout << "\n对空闲分区进行合并\n";
wf.MergerFreeMemo();
wf.print();
return 0;
}
至此,实验二已经完成。