一、实验内容
主存储器空间的分配和回收。
二、实验目的
一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。
三、实验原理
模拟在可变分区管理方式下采用最先适应算法实现主存分配和回收。
(1)可变分区方式是按作业需要的主存空间大小来分割分区的。当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。l例如:
为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:
起 址 | 长 度 | 状 态 | |
第一栏 | 14 K | 12 K | 未 分 配 |
第二栏 | 32 K | 96 K | 未 分 配 |
M | M | M | M |
其中,起址——指出一个空闲区的主存起始地址。
长度——指出从起始地址开始的一个连续空闲的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区。
(2) 当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。
(3) 采用最先适应算法分配主存空间。
按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。当空闲区大于需要量时,一部分用来装入作业,另一部分仍为空闲区登记在空闲区说明表中。
由于本实验是模拟主存的分配,所以把主存区分配给作业后并不实际启动装入程序装入作业,而用输出“分配情况”来代替。
(4) 当一个作业执行结束撤离时,作业所占的区域应该归还,归还的区域如果与其它空闲区相邻,则应合成一个较大的空闲区,登记在空闲区说明表中。
(5) 请按最先适应算法设计主存分配和回收的程序。假设初始时主存中没有作业,现按下面序列进行内存的申请与释放:
作业1申请300K,作业2申请100K,作业1释放300K,作业3申请150K,
作业4申请30K, 作业5申请40K, 作业6申请60K, 作业4释放30K。
请你为它们进行主存分配和回收,把空闲区说明表的初值以及每次分配或回收后的变化显示出来或打印出来。
#include<stdio.h>
#include<string.h>
#pragma warning(disable:4996)
//定义当前内存大小
#define SIZE 512
/*
定义两张表:
空闲区域记录表:按照起址顺序记录空闲区域的信息
工作区域记录表:按照起址顺序记录工作区域的信息
*/
//定义作业的结构体
typedef struct Task
{
char name[20];//记录作业名称
int start;//记录作业的起址
int length;//记录作业所需存储空间的长度;
int end;//定义作业的结束地址=start+length
}Task;
//定义两张表格
Task Free[100];//可以记录共100条空闲区域信息
Task Busy[100];//可以记录共100条工作区域信息
int FreeCounts; //记录空闲区域表中有几条信息
int BusyCounts; //记录工作区域表中有几条信息
//定义打印表格信息的函数
void print(Task* p, int count, int flag)//flag : 0-打印空闲区域表 1-打印工作区域表
{
switch (flag)
{
case 1:
printf("Work Area:>\n");
break;
case 0:
printf("Free Area:>\n");
break;
}
printf("作业名称 作业起址 作业长度 作业尾址\n");
for (int i = 0; i < count; ++i)
{
Task work = *(p + i);
printf("%4s %4d %4d %4d\n", work.name, work.start, work.length, work.end);
}
printf("\n");
}
//初始化表格:向空闲区域表中记录第一条信息
void Init()
{
FreeCounts = 1;
BusyCounts = 0;
strcpy(Free[0].name, "空闲区域");
Free[0].start = 0;
Free[0].length = SIZE;
Free[0].end = SIZE;
//打印两个表格
print(Free, FreeCounts, 0);
print(Busy, BusyCounts, 1);
}
//定义对两个表中的信息按照起址进行排序的函数
void AddressSort(Task* p,int count)
{
for (int i = 0; i < count-1; ++i)
{
for (int j = (i + 1); j < count; ++j)
{
if (( * (p + i)).start > (*(p+j)).start)
{
Task temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
}
}
}
}
//定义判断此时空闲表中是否有可以合并的空闲区
void FreeCombine()
{
for (int i = 0; i < (FreeCounts - 1); ++i)
{
if (Free[i].end == Free[i + 1].start)
{
Free[i].start = Free[i].start;
Free[i].length = Free[i].length + Free[i + 1].length;
Free[i].end = Free[i + 1].end;
for (int j = (i + 1); j < FreeCounts; ++j)
{
Free[j] = Free[j + 1];
}
FreeCounts--;
}
}
}
//申请内存空间
char name[20];//作业的名称
int num;//作业所需的内存空间
void Input()
{
printf("\nInput the name of the task:>");
scanf("%s", name);
printf("\nInput the size of the task:>");
scanf("%d", &num);
}
/*
分配存储空间需要完成:
1.在空闲区域中查找首先满足其所需内存大小的空闲区域
2.修改空闲区域表中该空闲记录的信息
3.将该作业的信息记录到工作区域表中
4.给出分配结果
*/
//分配存储空间
void Allocation(int n)
{
int flag = 0;//判断分配情况 0-未分配 1-已分配
for (int i = 0; i < FreeCounts; ++i)
{
//空闲区域刚好等于作业所需内存大小
if (n == Free[i].length)
{
BusyCounts++;
strcpy(Busy[BusyCounts-1].name, name);
Busy[BusyCounts-1].start = Free[i].start;
Busy[BusyCounts-1].length = n;
Busy[BusyCounts-1].end = Free[i].end;
for (int k = i; k <= FreeCounts - 1; ++i)
{
Free[k] = Free[k + 1];
}
FreeCounts--;
//分配完成,跳出循环
flag = 1;
break;
}
//空闲区域大于作业所需内存大小
else if (n < Free[i].length)
{
//调整工作区域表
BusyCounts++;
strcpy(Busy[BusyCounts-1].name,name);
Busy[BusyCounts-1].start = Free[i].start;
Busy[BusyCounts-1].length = n;
Busy[BusyCounts-1].end = Free[i].start + n;
//调整空闲区域表
Free[i].start = Busy[BusyCounts-1].end;
Free[i].length = Free[i].length - n;
//分配完毕,跳出循环
flag = 1;
break;
}
}
switch (flag)
{
case 0:
printf("\nAllocation failed\n");
break;
case 1:
printf("\nAssignment succeeded\n");
break;
}
}
void Apply()
{
Input();
Allocation(num);
printf("\n");
print(Free, FreeCounts, 0);
print(Busy, BusyCounts, 1);
}
//定义释放空间的文件名
char RelaseName[20];
//作业空间的释放
void RelaseInput()
{
printf("\nInput the name of the task:> ");
scanf("%s", RelaseName);
}
void RelaseAllocation(char *name)
{
int flag = 0;//确定是否完成释放 0-未完成 1-已完成
for (int i = 0; i < BusyCounts; ++i)
{
if (strcmp(RelaseName, Busy[i].name) == 0)
{
FreeCounts++;
strcpy(Free[FreeCounts - 1].name, "空闲区域");
Free[FreeCounts - 1].start = Busy[i].start;
Free[FreeCounts - 1].length = Busy[i].length;
Free[FreeCounts - 1].end = Busy[i].end;
for (int j = i; j < BusyCounts; ++j)
{
Busy[j] = Busy[j + 1];
}
BusyCounts--;
//进行空闲区域排序。并进行相邻空闲区域的合并
AddressSort(Free,FreeCounts);
FreeCombine(Free,FreeCounts);
//完成释放,跳出循环
flag = 1;
break;
}
if (i == BusyCounts - 1)
{
break;
}
}
switch (flag)
{
case 0:
printf("\nRelase Failed\n");
break;
case 1:
printf("\nRelase Succeed\n");
break;
}
}
void Relase()
{
RelaseInput();
RelaseAllocation(RelaseName);
print(Free, FreeCounts, 0);
print(Busy, BusyCounts, 1);
}
//定义菜单函数
void menu()
{
while (1)
{
printf("---------Menu--------\n");
printf("1.AllocationInit \n");
printf("2.AllocationApply \n");
printf("3.AllocationFree \n");
printf("4.Exit \n");
printf("---------------------\n");
printf("Input your choice :>");
int choice;
scanf("%d", &choice);
switch (choice)
{
case 1:
Init();
break;
case 2:
Apply();
break;
case 3:
Relase();
break;
case 4:
exit(0);
default:
printf("Input Error\n");
break;
}
}
}
int main()
{
menu();
return 0;
}