一、实验目的
二、实验类型
综合性实验。综合高级语言、数据结构、存储管理模型等多方面的知识
三、实验示例
例题
设计一个可变分区存储管理方案。并编写模拟程序实现之。要求通过文件形式定义空闲区表,能随意输入作业及需要分配的空间;分别使用最先适应算法、最佳适应算法和最坏适应算法对输入的作业进行空间分配;能显示系统空闲表和已分配空间表。
可变分区方式是按作业需要的主存空间大小来分区。当装入一个作业时,首先要查看是否有足够的空闲空间来分配,若有则按指定的分配方式进行分配;否则作业不能装入。随着作业的装入和撤离主存空间被分为若干个大大小小的不连续的区间,为了表明各区间的状态可以用一个内存分区表如下结构所示来表示。
typedef struct node
{
int start;//起始地址
int length;//长度
char tag[20];//标志
}job;
1)可变分区的三种分配算法就是为作业分配主存空间的方法。
●最先适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入第一个满足条件的空间中去。
● 最佳适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入满足条件的空闲空间中最小的一个空间中去。
● 最坏适应算法:在空闲区间中查询满足作业需要的空间,并将作业装入满足条件的空闲空间中最大的一个空间中去。
从三种算法的说明可以看出,分配空间的过程主要可以分两步:
● 查询所有满足作业需求的空间块。
● 按照指定的算法将作业装入空间块中。
编写并调试完成可变分区存储管理程序。
分配算法:最先适应算法、最佳适应算法和最坏适应算法。
回收算法:考虑释放区相邻存储区的状态
要求打印每个作业的内存分配情况。
具体实现:
头文件及全局变量
class MyLinkedList {
public:
struct LinkedNode //内存分区表
{
string name;//作业名称
int start;
int length;
LinkedNode* next = nullptr;
// LinkedNode(string name, int start, int length) : name(name),
// start(0), length(length), next(nullptr){}
LinkedNode(string name, int start, int length){
this->name = name;
this->start = 0;
this->length = length;
this->next = nullptr;
}
LinkedNode(LinkedNode const &node){ //拷贝复制函数
name = node.name;
start = node.start;
length = node.length;
next = node.next;
}
}* tmp = nullptr;
LinkedNode* dummy_head;
MyLinkedList() {
//虚拟头节点
dummy_head = new LinkedNode("dummy_head", 0, 0);
}
void disp(){
cout << "作业名\t起始地址\t所占内存" << endl;
LinkedNode* tmp = dummy_head->next;
int begin = 0;
while(true){
if(tmp == nullptr){ //遍历到链表末端了
if(begin != content)
cout << "空闲区\t" << begin << "\t\t" << content - begin << endl;
break;
}
if(begin == 0){
if(dummy_head->next->start != 0)
cout << "空闲区\t" << 0 << "\t\t" << dummy_head->next->start - begin << endl;
else
cout << tmp->name << "\t\t" << tmp->start << "\t\t" << tmp->length << endl;
}
else {
if (tmp->start == begin) {
cout << tmp->name << "\t\t" << tmp->start << "\t\t" << tmp->length << endl;
} else if (tmp->start > begin) {
cout << "空闲区\t" << begin << "\t\t" << tmp->start - begin << endl;
begin = tmp->start;
continue;
}
}
begin = tmp->start + tmp->length;
tmp = tmp->next;
}
}
bool queue(string name, int length){ //内存不足,先排队
LinkedNode tmp(name, 0, length);
}
} main_link;
//链表为空,相当于空闲区在前面
bool insert_when_empty(MyLinkedList::LinkedNode new_comer){
//链表为空,相当于空闲区在前面
if(content >= new_comer.length) { //1.资源满足
main_link.dummy_head->next = new MyLinkedList::LinkedNode(new_comer);
new_comer.start = 0;
job_number++;
cout << "在地址为 0 处插入成功!" << endl;
return true;
}
else{ //2.资源不足
cout << "资源不足,插入失败。" << endl;
return false;
}
}
bool Al_first(MyLinkedList::LinkedNode new_comer){
//链表为空,相当于空闲区在前面
if(job_number == 0){
return insert_when_empty(new_comer);
}
//链表不为空
MyLinkedList::LinkedNode* tmp1 = main_link.dummy_head->next, *tmp2 = tmp1->next; //双指针
//1.空闲区夹中间
for(; tmp2 != nullptr; tmp1 = tmp1->next, tmp2 = tmp2->next){
int sub = tmp2->start - (tmp1->start + tmp1->length);
if(sub >= new_comer.length){ //资源满足
new_comer.next = tmp1->next;
tmp1->next = &new_comer;
new_comer.start = tmp1->start + tmp1->length;
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
}
//2.空闲区在最后
if(content - (tmp1->start + tmp1->length) >= new_comer.length){ //资源满足
new_comer.next = tmp1->next;
new_comer.next = nullptr;
new_comer.start = tmp1->start + tmp1->length;
tmp1->next = new MyLinkedList::LinkedNode(new_comer);
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
cout << "资源不足,插入失败。" << endl;
return false;
}
bool Al_best(MyLinkedList::LinkedNode new_comer){
//链表为空,相当于空闲区在前面
if(job_number == 0){
return insert_when_empty(new_comer);
}
//链表不为空
MyLinkedList::LinkedNode* tmp1 = main_link.dummy_head, *tmp2 = nullptr; //双指针
int flag = 0;
int record;
int tmp;
//找符合条件最小空闲区的起始地址
while(tmp1->next){
if(flag == 0){ //第一个作业前面的空闲区(0也记录)
record = tmp1->next->start;
tmp2 = tmp1;
flag = 1;
}else { //第一个作业之后(前面肯定有作业)
tmp = tmp1->next->start - tmp1->start - tmp1->length;
if(record == 0 && tmp >= new_comer.length){ //第一次有足够容量,直接存入
record = tmp;
tmp2 = tmp1;
flag = 2;
}else if(tmp >= new_comer.length && tmp < record){ //第一次后,有比其更小的空间,且资源满足,则更新
record = tmp;
tmp2 = tmp1;
flag = 3;
}
}
tmp1 = tmp1->next;
}
tmp = content - tmp1->start - tmp1->length;
//1.资源满足情况a:最后一段空闲区
if(tmp >= new_comer.length && record > tmp){
new_comer.next = tmp1->next;
tmp1->next = &new_comer;
new_comer.start = tmp1->start + tmp1->length;
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
if(record != 0) {
//2.资源满足情况b:不是最后一段空闲区
new_comer.next = tmp2->next;
tmp2->next = &new_comer;
new_comer.start = tmp2->start + tmp2->length;
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
else{
//3.资源不足
cout << "资源不足,插入失败。" << endl;
return false;
}
}
bool Al_worst(MyLinkedList::LinkedNode new_comer){
//链表为空,相当于空闲区在前面
if(job_number == 0){
return insert_when_empty(new_comer);
}
//链表不为空
MyLinkedList::LinkedNode* tmp1 = main_link.dummy_head, *tmp2 = nullptr; //双指针
int flag = 0;
int record;
int tmp;
//找符合条件最大空闲区的起始地址
while(tmp1->next){
if(flag == 0){ //第一个作业前面的空闲区(0也记录)
record = tmp1->next->start;
tmp2 = tmp1;
flag = 1;
}else { //第一个作业之后(前面肯定有作业)
tmp = tmp1->next->start - tmp1->start - tmp1->length;
if(record == 0 && tmp >= new_comer.length){ //第一次有足够容量,直接存入
record = tmp;
tmp2 = tmp1;
flag = 2;
}else if(tmp >= new_comer.length && tmp > record){ //第一次后,有比其更大的空间,且资源满足,则更新
record = tmp;
tmp2 = tmp1;
flag = 3;
}
}
tmp1 = tmp1->next;
}
tmp = content - tmp1->start - tmp1->length;
//1.资源满足情况a:最后一段空闲区
if(tmp >= new_comer.length && record < tmp){
new_comer.next = tmp1->next;
tmp1->next = &new_comer;
new_comer.start = tmp1->start + tmp1->length;
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
if(record != 0) {
//2.资源满足情况b:不是最后一段空闲区
new_comer.next = tmp2->next;
tmp2->next = &new_comer;
new_comer.start = tmp2->start + tmp2->length;
job_number++;
cout << "在地址为 " << new_comer.start << " 处插入成功" << endl;
return true;
}
else{
//3.资源不足
cout << "资源不足,插入失败。" << endl;
return false;
}
}
//回收算法
bool garbage_recycle(){
string name;
cout << "请输入要回收的作业名:";
cin >> name;
MyLinkedList::LinkedNode* tmp1 = main_link.dummy_head, *tmp2 = tmp1->next; //双指针
while(tmp2 != nullptr && tmp2->name != name){ //循环直到:快指针遍历完毕 或者 找到这个作业
tmp1 = tmp1->next;
tmp2 = tmp2->next;
}
if(tmp2 == nullptr) //没找到该作业
return false;
//找到了
else{
if(tmp1->name == "dummy_head"){ //就是第一个作业
if(tmp2->next == nullptr && tmp2->length == content)
cout << "无上、下邻空间,本内存回收成功!";
else
cout << "有下邻空间,本内存回收成功!";
}
else if(tmp1->start + tmp1->length < tmp2->start){
//1. 有上、下邻空间
if(tmp2->next == nullptr){
cout << "有上、下邻空间,本内存回收成功!";
}
else{ //2. 有上邻空间
cout << "有上邻空间,回收成功!";
}
}
//3. 有下邻空间
else if(tmp2->next->start > tmp2->start + tmp2->length){
cout << "有下邻空间,本内存回收成功!";
}
//4. 无上、下邻空间
else
cout << "无上、下邻空间,本内存回收成功!";
cout << endl;
tmp1->next = tmp2->next;
job_number--;
return true;
}
}
MyLinkedList init(){
MyLinkedList link = MyLinkedList();
return link;
}
MyLinkedList::LinkedNode create_node(){
string name;
int length;
cout << "请输入作业名:"; cin >> name;
cout << "请输入作业所需资源:";
cin >> length;
return MyLinkedList::LinkedNode(name, 0, length);
}
void menu()//提供服务菜单
{
printf("1.最先适应算法.");
printf("\n2.最佳适应算法.");
printf("\n3.最坏适应算法.");
printf("\n4.回收内存算法.");
printf("\n5.结束程序请按5.\n");
while(true) {
int m;
cin >> m;
switch (m) {
case 1:
Al_first(create_node());
break;
case 2:
Al_best(create_node());
break;
case 3:
Al_worst(create_node());
break;
case 4:
garbage_recycle();
break;
case 5:
cout << "程序成功终止!";
return;
default:
printf("输入错误!,请重新输入\n");
menu();
}
main_link.disp();
}
}
int main()
{
menu();
printf("\n");
system("pause");//终端窗口停靠
return 0;
}
说明:
- 左图使用最先适应算法,找到第一个够用的空闲区就分配资源。
- 中间的图使用最佳适应算法,遍历了所有空闲区,将作业分配到最小且资源足够的空闲区。
- 右图使用最坏适应算法,遍历了所有空闲区,将作业分配到最大且资源足够的空闲区。