- 实现动态分区的分配算法。
- 最佳适配算法选择内存空闲块中最适合进程大小的块分配。
- 首次适配算法从开始地址查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程。
- 最差适配算法选择最大空闲块减少碎片。
- 相邻空闲区的合并问题,要求考虑四种情况:
- 释放区下邻空闲区(低地址邻接)
- 释放区上邻空闲区(高地址邻接)
- 释放区上下都与空闲区邻接
- 释放区上下邻都与空闲区不邻接
实验思路 数据结构假设初始状态下,可用的内存空间为640KB,并有下列的请求序列:
•作业1申请130KB
•作业2申请60KB
•作业3申请100KB
•作业2释放60KB
•作业4申请200KB
•作业3释放100KB
•作业1释放130KB
•作业5申请140KB
•作业6申请60KB
•作业7申请50KB
应用一个双向链表的结构来实现内存管理
先看链表节点类:
- freeTable是每个节点的数据,包括分区序号,起始地址,分区大小,分区状态
class freeTable { public: int num; //分区序号 long address; //起始地址 long length; //分区大小 int state; //分区状态 freeTable(int num, long address, long length, int state); };
- Node类是节点类,包含节点数据类freeTable,前后指针
#include "freeTable.h" typedef freeTable ElemType; class Node { public: ElemType data; Node* prior; //前趋指针 Node* next; //后继指针 Node(int num, long address, long length, int state); Node(int num, long address, long length, int state, Node* pre,Node* nxt); };
再看内存管理类:
MemoryManager类是用于模拟内存的一个类,用于对外提供接口来申请/释放接口,其本质是一个双向链表
class MemoryManager { private: Node* head; int nodeNum=1; int maxLenth; public: MemoryManager(int _num, long _address, long _length, int _state); MemoryManager(long _length); void show(); int requestMemory(long memoryLen);//申请内存空间,返回申请到的内存空间地址,失败则返回-1 int bestFit(long memoryLen);//最佳适配算法 void freeMemory(int memoryNum);//释放内存 int firstFit(long memoryLen);//首次适配算法 int maxFit(long memoryLen);//最差适配算法 int allocateMemory(Node* reAllocatedNode, long memoryLen);//分配内存 };
假设 *** 作系统本身就占用了40KB的容量,这一部分将被放在头结点中,所以构造函数如下:
MemoryManager::MemoryManager(int _num, long _address, long _length, int _state) { head = new Node(_num, _address, _length, _state); } MemoryManager::MemoryManager(long _length):MemoryManager(0,0,40,1)//假设 *** 作系统本身占用40KB的容量 { if (_length <= 40) { cout << "分配的内存不足" << endl; exit(0); } maxLenth = _length; head->next = new Node(1, 40, maxLenth - 40, 0,head,0); }内存释放算法
内存的释放其实只需要将state置为0即可,但是考虑到相邻空闲区的合并问题,需要考虑四种情况:
- 释放区下邻空闲区(低地址邻接)
- 释放区上邻空闲区(高地址邻接)
- 释放区上下都与空闲区邻接
- 释放区上下邻都与空闲区不邻接
如上四种情况,综合下来只需要考虑两个相邻空闲区的合并问题,如合并下邻空闲区,合并上邻空闲区.事实上,这两个问题只需要用同一段代码实现即可,思路如下:
p与p的前驱节点合并
- 修改p前驱的data值
- 将p前驱的后继指向p的后继
- p后继的前驱指向p的前驱
综上可以将p独立出来,delete p即可
p->prior->data.length += p->data.length; p->prior->next = p->next; if (p->next) { p->next->prior = p->prior; } delete p;
p与p的后继节点合并
这种情况只需要将p移动到p的后继节点,然后执行上面的算法即可
p与p的前驱节点和后继节点合并
这种情况只需要将p指向后继节点,然后两次执行上面的算法即可
综上所述,内存释放算法如下:
void MemoryManager::freeMemory(int memoryNum) { ///三个不同的内存分配算法 算法实现思路/// 释放内存 /// /// 要释放的内存的序号 if (memoryNum<=0) { cout << "不可以释放该内存" << endl; exit(1); } Node* p = head; while (p) { if (p->data.num == memoryNum) { p->data.state = 0; break; } p = p->next; } if (p == nullptr) { cout << "未找到该内存空间" << endl; exit(1); } if (p->next && p->next->data.state == 0) {//当释放区下邻空闲区(低地址邻接) p = p->next;//将p下移 } while (p->prior && p->prior->data.state == 0) { //释放区上邻空闲区(高地址邻接) //下面的 *** 作会将p和p前面的空间合并,并且循环直到p前面不为空闲区 p->prior->data.length += p->data.length; p->prior->next = p->next; if (p->next) { p->next->prior = p->prior; } Node* temp = p; p = p->prior; delete temp; } }
下面的三个算法第一步是找出要分配的内存空间,第二步都是将内存空间开辟并分配内存,因为第二步三个算法都是一样的实现过程,所以我们可以将代码抽取出来封装在一个函数中,代码如下
内存空间分配算法
大致思路是
如要分配Node2的空间
- 新建一个节点NewNode,设置节点NewNode的data值,然后改变NewNode的前后指针
- 然后改变Node2的前驱节点的next指向和Node2节点的pre指向
int MemoryManager::allocateMemory(Node* reAllocatedNode,long memoryLen) { if (reAllocatedNode && reAllocatedNode->data.length < memoryLen) { cout << "内存不足以分配" << endl; exit(1); } //开始分配 //这块指针节点将被分配成两部分,第一部分为被分配的空间,第二部分为未分配的空间 nodeNum++; if (reAllocatedNode->data.length == memoryLen) { //如果被分配的空间大小和申请的空间大小相同,则直接改变状态即可 reAllocatedNode->data.state = 1; reAllocatedNode->data.num = nodeNum; return nodeNum; } long nodeAddress = reAllocatedNode->data.address; Node* newNode = new Node(nodeNum, nodeAddress, memoryLen, 1, reAllocatedNode->prior, reAllocatedNode); //指针指向改变 reAllocatedNode->data.address += memoryLen; reAllocatedNode->data.length -= memoryLen; reAllocatedNode->prior->next = newNode; reAllocatedNode->prior = newNode; return nodeNum; }
而第一步就根据算法的思想来找到要分配的内存空间
最佳适配算法最佳适配算法选择内存空闲块中最适合进程大小的块分配
先遍历链表找出空间最大的空闲块,然后再遍历一次链表,根据前面找到的最大的空间块来找到满足最小的空间要求的空闲块,然后执行内存空间分配算法即可
代码如下:
int MemoryManager::bestFit(long memoryLen) { ///首次适配算法/// //最佳适配算法,选择内存空闲块中最适合进程大小的块分配 /// 申请内存空间,返回申请到的内存空间地址,失败则返回-1 /// /// 要申请的内存长度 ///Node* p = head->next,*reAllocateMemoryNode=p; while (p) { if (p->data.state==0) { if (p->data.length >= reAllocateMemoryNode->data.length) { reAllocateMemoryNode = p; } } p = p->next; } p = head; while (p) { if (p->data.state==0) {//空间空闲 if (p->data.length > memoryLen && p->data.length <= reAllocateMemoryNode->data.length) { //当前指针节点的空间合适且比上次定位的指针节点空间小 //则改变定位指针的位置 reAllocateMemoryNode = p; } } p = p->next; } return allocateMemory(reAllocateMemoryNode, memoryLen); }
首次适配算法从开始地址查找符合要求的块,所查找到的第一个满足要求的空闲块就分配给进程。
遍历一次链表直到第一次找到满足空间要求的空闲块
int MemoryManager::firstFit(long memoryLen) { Node* reAllocateMemoryNode = head->next; while (reAllocateMemoryNode) {//找到第一个适配的内存空间 if (reAllocateMemoryNode->data.state == 0) { if (reAllocateMemoryNode->data.length >= memoryLen) { break; } } reAllocateMemoryNode = reAllocateMemoryNode->next; } return allocateMemory(reAllocateMemoryNode, memoryLen); }最差适配算法
最差适配算法选择最大空闲块减少碎片
遍历一次找到最大的空间块即可
int MemoryManager::maxFit(long memoryLen) { Node* p = head->next, * reAllocateMemoryNode = p; while (p) { if (p->data.state == 0) { if (p->data.length >= reAllocateMemoryNode->data.length) { reAllocateMemoryNode = p; } } p = p->next; } return allocateMemory(reAllocateMemoryNode, memoryLen); }运算结果
主函数如下
int main() { MemoryManager memoryManager(640); memoryManager.show(); cout << "作业1申请130KB" << endl; int first = memoryManager.requestMemory(130);memoryManager.show(); cout << "作业2申请60KB" << endl; int second = memoryManager.requestMemory(60);memoryManager.show(); cout << "作业3申请100KB" << endl; int third = memoryManager.requestMemory(100);memoryManager.show(); cout << "作业2释放60KB" << endl; memoryManager.freeMemory(second); memoryManager.show(); cout << "作业4申请200KB" << endl; int four = memoryManager.requestMemory(200);memoryManager.show(); cout << "作业3释放100KB" << endl; memoryManager.freeMemory(third); memoryManager.show(); cout << "作业1释放130KB" << endl; memoryManager.freeMemory(first); memoryManager.show(); cout << "作业5申请140KB" << endl; int five = memoryManager.requestMemory(140); memoryManager.show(); cout << "作业6申请60KB" << endl; int six = memoryManager.requestMemory(60); memoryManager.show(); cout << "作业7申请50KB" << endl; int seven = memoryManager.requestMemory(70); memoryManager.show(); }最佳适配算法 首次适配算法 最差适配算法
源代码点我
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)