实验4 内存管理
一、实验目的
1、对内存管理的相关内容做进一步的理解。
2、了解内存管理的主要任务。
3、了解内存管理任务的主要实现方法。
4、通过编程加深理解内存的分配、回收等主要算法的原理。
二、实验内容及要求
1、在该实验中,采用可变分区方式完成对存储空间的管理(即存储空间的分配与回收工作)。
2、设计用来记录主存使用情况的数据结构:已分区表和空闲分区表。
3、在设计好的数据结构上设计一个主存分配算法,要求实现的基本功能操作有:寻找空闲分区,空闲分区表的修改,已分区表的修改。
4、在设计好的数据结构上设计一个主存回收算法。其中,若回收的分区有上邻空闲分区和(或)下邻空闲分区,要求合并为一个空闲分区登记在空闲分区表的一个表项里。
三、实验报告
1、程序中使用的数据结构及符号说明。
2、给出主要算法的流程图。
3、给出测试数据和运行结果,要求系统每进行一次分配或回收,都要给出内存映像图或已分配表及未分配表以观察内存的变化。
代码:
// OS4.1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include<stdio.h>
#include<stdlib.h>
#define OK 1 //完成
#define ERROR 0 //出错
typedef int Status;
typedef struct free_table//定义一个空闲区说明表结构
{
int num; //分区序号
long address; //起始地址
long length;//分区大小
int state; //分区状态
}ElemType;
typedef struct Node//线性表的双向链表存储结构
{
ElemType data;
struct Node*prior;//前趋指针
struct Node *next;//后继指针
}Node, *LinkList;
LinkList first;//头结点
LinkList end;//尾结点
int flag;//记录要删除的分区序号
Status Initblock()//开创带头结点的内存空间链表
{
first = (LinkList)malloc(sizeof(Node));
end = (LinkList)malloc(sizeof(Node));
first->prior = NULL;
first->next = end;
end->prior = first;
end->next = NULL;
end->data.num = 1;
end->data.address = 40;
end->data.length = 600;
end->data.state = 0;
return OK;
}
void sort()//分区序号重新排序
{
Node *p = first->next, *q;
q = p->next;
for (; p != NULL; p = p->next)
{
for (q = p->next; q; q = q->next)
{
if (p->data.num >= q->data.num)
{
q->data.num += 1;
}
}
}
}//显示主存分配情况
void show()
{
int flag = 0;//用来记录分区序号
Node *p = first;
p->data.num = 0;
p->data.address = 0;
p->data.length = 40;
p->data.state = 1;
sort();
printf("\n\t\t》主存空间分配情况《\n");
printf("**********************************************************\n\n");
printf("分区序号\t起始地址\t分区大小\t分区状态\n\n");
while (p)
{
printf("%d\t\t%d\t\t%d", p->data.num, p->data.address, p->data.length);
if (p->data.state == 0)
printf("\t\t空闲\n\n");
else
printf("\t\t已分配\n\n");
p = p->next;
}
printf("**********************************************************\n\n");
}//首次适应算法
Status First_fit(int request) {//为申请作业开辟新空间且初始化
Node *p = first->next;
LinkList temp = (LinkList)malloc(sizeof(Node));
temp->data.length = request;
temp->data.state = 1;
p->data.num = 1;
while (p)
{
if ((p->data.state == 0) && (p->data.length == request))
{//有大小恰好合适的空闲块
p->data.state = 1;
return OK;
break;
}
else if ((p->data.state == 0) && (p->data.length > request))
{//有空闲块能满足需求且有剩余
temp->prior = p->prior;
temp->next = p;
temp->data.address = p->data.address;
temp->data.num = p->data.num;
p->prior->next = temp;
p->prior = temp;
p->data.address = temp->data.address + temp->data.length;
p->data.length -= request;
p->data.num += 1;
return OK;
break;
}
p = p->next;
}
return ERROR;
}//最佳适应算法
Status Best_fit(int request)
{
int ch;//记录最小剩余空间
Node *p = first;
Node *q = NULL;//记录最佳插入位置
LinkList temp = (LinkList)malloc(sizeof(Node));
temp->data.length = request;
temp->data.state = 1;
p->data.num = 1;
while (p)//初始化最小空间和最佳位置
{
if ((p->data.state == 0) && (p->data.length >= request))
{
if (q == NULL)
{
q = p;
ch = p->data.length - request;
}
else if (q->data.length > p->data.length)
{
q = p;
ch = p->data.length - request;
}
}
p = p->next;
}
if (q == NULL) return ERROR;
//没有找到空闲块
else if (q->data.length == request)
{
q->data.state = 1;
return OK;
}
else
{
temp->prior = q->prior;
temp->next = q;
temp->data.address = q->data.address;
temp->data.num = q->data.num;
q->prior->next = temp;
q->prior = temp;
q->data.address += request;
q->data.length = ch;
q->data.num += 1;
return OK;
}
return OK;
}//最差适应算法
Status Worst_fit(int request)
{
int ch;//记录最大剩余空间
Node *p = first->next;
Node *q = NULL;//记录最佳插入位置
LinkList temp = (LinkList)malloc(sizeof(Node));
temp->data.length = request;
temp->data.state = 1;
p->data.num = 1;
while (p)//初始化最大空间和最佳位置
{
if (p->data.state == 0 && (p->data.length >= request))
{
if (q == NULL)
{
q = p;
ch = p->data.length - request;
}
else if (q->data.length < p->data.length)
{
q = p;
ch = p->data.length - request;
}
}
p = p->next;
}
if (q == NULL) return ERROR;//没有找到空闲块
else if (q->data.length == request)
{
q->data.length = 1;
return OK;
}
else
{
temp->prior = q->prior;
temp->next = q;
temp->data.address = q->data.address;
temp->data.num = q->data.num;
q->prior->next = temp;
q->prior = temp;
q->data.address += request;
q->data.length = ch;
q->data.num += 1;
return OK;
} return OK;
}//分配主存
Status allocation(int a)
{
int request;//申请内存大小
printf("请输入申请分配的主存大小(单位:KB):");
scanf_s("%d", &request);
if (request < 0 || request == 0)
{
printf("分配大小不合适,请重试!");
return ERROR;
}
switch (a)
{
case 1://默认首次适应算法
if (First_fit(request) == OK)
printf("\t****分配成功!****");
else printf("\t****内存不足,分配失败!****");
return OK;
break;
case 2://选择最佳适应算法
if (Best_fit(request) == OK)
printf("\t****分配成功!****");
else printf("\t****内存不足,分配失败!****");
return OK;
break;
case 3://选择最差适应算法
if (Worst_fit(request) == OK)
printf("\t****分配成功!****");
else printf("\t****内存不足,分配失败!****");
return OK;
break;
}
}
Status deal1(Node *p)//处理回收空间
{
Node *q = first;
for (; q != NULL; q = q->next)
{
if (q == p)
{
if (q->prior->data.state == 0 && q->next->data.state != 0)
{
q->prior->data.length += q->data.length;
q->prior->next = q->next;
q->next->prior = q->prior;
q = q->prior;
q->data.state = 0;
q->data.num = flag - 1;
}
if (q->prior->data.state != 0 && q->next->data.state == 0)
{
q->data.length += q->next->data.length;
q->next = q->next->next;
q->next->next->prior = q;
q->data.state = 0;
q->data.num = flag;
}
if (q->prior->data.state == 0 && q->next->data.state == 0)
{
q->prior->data.length += q->data.length;
q->prior->next = q->next;
q->next->prior = q->prior;
q = q->prior;
q->data.state = 0;
q->data.num = flag - 1;
}
if (q->prior->data.state != 0 && q->next->data.state != 0)
{
q->data.state = 0;
}
}
}
return OK;
}
Status deal2(Node *p)//处理回收空间
{
Node *q = first;
for (; q != NULL; q = q->next)
{
if (q == p)
{
if (q->prior->data.state == 0 && q->next->data.state != 0)
{
q->prior->data.length += q->data.length;
q->prior->next = q->next;
q->next->prior = q->prior;
q = p->prior;
q->data.state = 0;
q->data.num = flag - 1;
}
if (q->prior->data.state != 0 && q->next->data.state == 0)
{
q->data.state = 0;
}
if (q->prior->data.state == 0 && q->next->data.state == 0)
{
q->prior->data.length += q->data.length;
q->prior->next = q->next;
q->next->prior = q->prior;
q = q->prior;
q->data.state = 0;
q->data.num = flag - 1;
}
if (q->prior->data.state != 0 && q->next->data.state != 0)
{
q->data.state = 0;
}
}
}
return OK;
}//主存回收
Status recovery(int flag)
{
Node *p = first;
for (; p != NULL; p = p->next)
{
if (p->data.num == flag)
{
if (p->prior == first)
{
if (p->next != end)//当前P指向的下一个不是最后一个时
{
if (p->next->data.state == 0)//与后面的空闲块相连
{
p->data.length += p->next->data.length;
p->next->next->prior = p;
p->next = p->next->next;
p->data.state = 0;
p->data.num = flag;
}
else p->data.state = 0;
}
if (p->next == end)//当前P指向的下一个是最后一个时
{
p->data.state = 0;
}
}//结束if(p->prior==block_first)的情况
else if (p->prior != first)
{
if (p->next != end)
{
deal1(p);
}
else
{
deal2(p);
}
}//结束if(p->prior!=block_first)的情况
}//结束if(p->data.num==flag)的情况
}
printf("\t****回收成功****");
return OK;
}//主函数
void main()
{
int i;//操作选择标记
int a;//算法选择标记
printf("**********************************************************\n");
printf("\t\t用以下三种方法实现主存空间的分配\n");
printf("\t(1)首次适应算法\t(2)最佳适应算法\t(3)最差适应算法\n");
printf("**********************************************************\n");
printf("\n");
printf("请输入所使用的内存分配算法:");
scanf_s("%d", &a);
while (a < 1 || a>3)
{
printf("输入错误,请重新输入所使用的内存分配算法:\n");
scanf_s("%d", &a);
}
switch (a)
{
case 1:printf("\n\t****使用首次适应算法:****\n"); break;
case 2:printf("\n\t****使用最佳适应算法:****\n"); break;
case 3:printf("\n\t****使用最坏适应算法:****\n"); break;
}
Initblock();//开创空间表
while (1)
{
show();
printf("\t1: 分配内存\t2: 回收内存\t0: 退出\n");
printf("请输入您的操作:");
scanf_s("%d", &i);
if (i == 1)
allocation(a);//分配内存
else if (i == 2)//内存回收
{
printf("请输入您要释放的分区号:");
scanf_s("%d", &flag);
recovery(flag);
}
else if (i == 0)
{
printf("\n退出程序\n");
break;//退出
}
else//输入操作有误
{
printf("输入有误,请重试!");
continue;
}
}
}
运行结果:
分配和回收测试的情况很多,自己试自己体会吧。