动态内存分配问题是现代操作系统必须要考虑的一个核心问题,老师最近要求我们用C语言实现一下书上的两种方法,首次适应算法和最佳适应算法,因为C语言的输入输出实在有些麻烦我就偷懒用了一下C++的输入输出和new函数,整体还是C语言(虽然不用类封装的话两者好像没啥大却别),那么先简短介绍一下两个算法的思路。
首次适应算法是当有作业申请内存时,将作业放置在主存中第一个足够装入它的可利用的空闲去中,说白了就是顺序遍历空闲区,第一个满足大小要求的就放进去,这个算法思想很简单,操作也很简单,造成的结果是低地址的空闲区被频繁利用,尽可能保留高地址的空闲区,低址部分不断被划分,会留下许多难以利用的,很小的空闲分区,称为碎片。而每次查找又都是从低址部分开始的,这无疑又会增加查找可用空闲分区时的开销。
比如一个作业要申请60KB,系统会顺序遍历主存空间,当遇到大小>60KB和状态为空闲时,就会把作业装入该部分内存中,所以先遍历分区1,大小不满足,分区2状态不满足,接下来分区3大小状态都满足,就装入该部分内存,即使分区5的大小刚刚好没有浪费但是系统还是会选择分区3。
那么最佳适应算法就是找到与作业申请的内存大小最相近的一个空闲区放进去,使剩下的空闲空间最小,不难理解上面这个例子那么系统就会把作业放入分区5,而不是分区3,当大小正好相等时这种算法的确很好,没有剩余的空闲空间,当作业申请的内存大小变成59KB呢?这是就会有1KB的空闲空间,这1KB就很难会有程序可以利用起来了, 这种分割会造成很多非常小的分散的空闲区,碎片多的话会对主存的访问效率产生影响,计算机的性能也会有影响,现代操作系统主要是利用页式或段式存储管理来解决碎片化问题,这里就不做详细解释了,有兴趣的可以自行百度(不是很难)。
接下来进入我的实现两个算法部分了,讲一下主要思路。
首先是分区结构体的定义
typedef struct freespace
{
int num; //分区号
int size; //分区大小
int address; //分区首地址
status state; //分区状态,FREE和BUSY
};
然后是分区的节点定义,主要利用了双链表结构,数据包含头指针、尾指针、数据域freespace变量,紧接着定义了全局变量first指针和last指针,并对他们初始化。
typedef struct node
{
freespace data;
node *head;
node *next;
}*Linklist;
第一个算法的主要思路就是对分区链表进行遍历,找到状态为FREE和data.size大于作业申请的size的节点,如果大小刚好相同,把节点的data.num直接改成作业号就可以了,如果大小比作业的大,那么还要对该分区进行分割,把作业节点插入该节点之前,然后把该节点的大小改成两个大小的差就可以了,注意一下头指针和尾指针在插入时候的赋值就可以了。
最佳遍历的思路和第一个差不多,但是多了一个查找最佳分配节点的步骤,就是要遍历每一个分区,计算分区大小和作业申请大小的差值,得到最小差值的节点地址,然后对该节点做上面的操作就可以了。
那么上代码咯
#include<iostream>
#include<stdlib.h>
using namespace std;
#define MAXSIZE 640
enum status { FREE, BUSY };
typedef struct freespace
{
int num; //分区号
int size; //分区大小
int address; //分区首地址
status state; //分区状态,FREE和BUSY
};
typedef struct node
{
freespace data;
node *head;
node *next;
}*Linklist;
Linklist first,last;
void initial()
{
first = new node;
last = new node;
first->head = NULL;
first->next = last;
last->head = first;
last->next = NULL;
last->data.address = 0;
last->data.size = MAXSIZE;
last->data.num = 0;
last->data.state = FREE;
}
void display()
{
cout << "****************主内存分配情况****************" << endl;
node *p = first->next;
while (p)
{
cout << "分区号:";
if (p->data.num == 0)
{
cout << "空闲区" << " " << "起始地址:" << p->data.address << " " << "终止地址:" << p->data.address+p->data.size<<
" " << "分区大小:" <<
p->data.size << "KB" << " " << "状态:空闲" << endl;
}
else
{
cout << p->data.num;
cout << " " << "起始地址:" << p->data.address << " " << "终止地址:" << p->data.address + p->data.size << " "
"分区大小:" << p->data.size
<< "KB" << " " << "状态:";
if (p->data.state == FREE)
cout << "空闲" << endl;
else if (p->data.state == BUSY)
cout << "占用" << endl;
}
p = p->next;
}
cout << "**********************************************" << endl << endl;
}
int firstAlloc()//首次分配
{
int num, size;
cout << "请输入作业号和分配的主存大小KB:" << endl;;
cin >> num >> size;
Linklist list = new node;
list->data.num = num;
list->data.size = size;
list->data.state = BUSY;
node *p = first->next;
while (p)
{
if (p->data.state == FREE&&p->data.size == size)//有大小刚好合适的空闲块
{
p->data.state = BUSY;
p->data.num = num;
display();
return 1;
}
if (p->data.state == FREE&&p->data.size > size)//有大小比他大的空闲块
{
list->head = p->head;
list->next = p;
list->data.address = p->data.address;
p->head->next = list;
p->head = list;
p->data.address = list->data.address + list->data.size;
p->data.size -= size;
display();
return 1;
}
p = p->next;
}
display();
return 0;
}
int bestAlloc()//最佳分配
{
int num, size;
cout << "请输入作业号和分配的主存大小KB:" << endl;;
cin >> num >> size;
int min_space=MAXSIZE;
Linklist list = new node;
list->data.num = num;
list->data.size = size;
list->data.state = BUSY;
node *p = first->next;
node *q = NULL;
while (p)//找到最佳位置
{
if ((p->data.size > size || p->data.size == size)&&p->data.state==FREE)
{
if (p->data.size - size < min_space)
{
q = p;
min_space = p->data.size - size;
}
}
p = p->next;
}
if (q == NULL)
{
return 0;
}
else
{
if (min_space == 0)
{
q->data.num = num;
q->data.state = BUSY;
display();
return 1;
}
else
{
list->head = q -> head;
list->next = q;
list->data.address = q->data.address;
q->head->next = list;
q->head = list;
q->data.address += size;
q->data.size -= size;
display();
return 1;
}
}
}
int recycle()//碎片整理
{
int num;
cout << "请输入你要回收内存的作业号:" << endl;
cin >> num;
node *p = first;
while (p)
{
if (p->data.num == num)
{
p->data.state = FREE;
p->data.num = 0;
if (p->head->data.state == FREE)//与前一块空闲区相邻,则合并
{
p->head->data.size += p->data.size;
p->head->next = p->next;
p->next->head = p->head;
}
if (p->next->data.state == FREE)//与后一块空闲区相邻,则合并
{
p->data.size += p->next->data.size;
p->next->next->head = p;
p->next = p->next->next;
}
break;
}
p = p->next;
}
display();
return 1;
}
void menu()
{
cout << "********************内存分配系统********************" << endl;
cout << "* 1.首次适应算法分配内存 *" << endl;
cout << "* 2.最佳适应算法分配内存 *" << endl;
cout << "* 3.查看主存分配情况 *" << endl;
cout << "* 4.回收主存 *" << endl;
cout << "* 5.溜溜球 *" << endl;
cout << "****************************************************" << endl;
cout << "请选择:" << endl;
}
void main()
{
initial();
int choose;
while (1)
{
menu();
cin >> choose;
switch (choose)
{
case 1:
firstAlloc();
break;
case 2:
bestAlloc();
break;
case 3:
display();
break;
case 4:
recycle();
break;
case 5:
exit(1);
break;
default :
cout << "请输入有效数字!" << endl;
break;
}
}
}
下面是测试的数据和测试的截图
首次适应算法(因为中间显示的很长就截了部分):
最佳适应算法(因为中间显示的很长就截了部分):
可以看出来主要是作业5的位置发生了变化,有兴趣的可以自己跑一下看一下中间过程,跟着程序走能对这个算法有很深的理解(每次调试的时候都深有体会!),那么就到此结束了,谢谢!