实验项目五存储管理
一、实验目的
1.熟悉内存空闲分区的分配方式;
2.理解动态分区存储管理方式;
3.掌握动态分区的分配与回收的过程。
二、实验内容
使用一个链表来模拟内存存储空间,建立内存块来记录内存分配使用情况,通过随机产生进程及其所需要的内存来模拟真实的进程。
通过给进程分配内存及回收来实现对动态分区存储管理方法。
编制程序完成上述内容,内存空间大小为100,进程数为5,每个进程所需空间为随机产生,大小为1~20,首先对5个进程进行内存分配,然后回收指定的进程空间,并进行适当的空闲分区合并操作,要求每次操作结束后都能显示当前的内存分配情况。
三、源程序及运行结果
源程序:
#include<stdio.h>
typedef struct MEMORY_BLOCK
{
int name; //进程名
int address; //起始地址
int length; //长度
int flag; //标志,表示该块是否被分配。
struct MEMORY_BLOCK *next;//指向下一个进程
}MEMORY_BLOCK;
#define NUM 5
#define LEN sizeof(MEMORY_BLOCK)
void allocation(MEMORY_BLOCK *Header,int name,int length_p)
{
MEMORY_BLOCK *temp,*t,*tt;
int minsize=2; //不可切割的分区阈值
t=Header;
while(t!=0)
{
if(t->length>length_p&&t->flag==0) break;
t=t->next;
}
if(t->length-length_p>minsize) //分割
{
temp=(MEMORY_BLOCK*)malloc(LEN);
temp->name=-1;
temp->flag=0;
temp->length=t->length-length_p;
temp->address=t->address+length_p;
t->name=name;
t->flag=1;
t->length=length_p;
temp->next=t->next;
t->next=temp;
}
else //直接分配
{
t->name=name;
t->flag=1;
}
}
void reclaim(int processname, MEMORY_BLOCK *Header)
{
MEMORY_BLOCK *temp,*t,*tt;
t=Header;
temp=t;
while(t->name!=processname)
{
temp=t;
t=t->next;
}
if(t->next!=NULL)//t非尾结点
if(temp->flag==0&&t->next->flag==0)//左右为空
{
temp->name=-1;
temp->length=temp->length+t->length+t->next->length;
tt=t->next;
temp->next=tt->next;
}
else if(temp->flag==0) //左为空
{
temp->name=-1;
temp->length=temp->length+t->length;
temp->next=t->next;
}
else if(t->next->flag==0) //右为空
{
t->name=-1;
t->length=t->length+t->next->length;
t->flag=0;
tt=t->next;
t->next=tt->next;
}
else // 左右不为空
{
t->name=-1;
t->flag=0;
}
else//t是尾结点
{
if(temp->flag==0) //左为空
{
temp->name=-1;
temp->length=temp->length+t->length;
temp=t->next;
}
else // 左不为空
{
t->name=-1;
t->flag=0;
}
}
}
void main() //主函数
{
int length_p,i,processname;
MEMORY_BLOCK *Header,*t;
Header=(MEMORY_BLOCK*)malloc(LEN);//初始化存储空间Header->name=-1;
Header->address=0;
Header->length=100;
Header->flag=0;
Header->next=NULL;
srand((int)time(0));
for(i=1;i<=NUM;i++)
{
length_p=rand()%20+1; //随机产生进程所需存储空间,至少为1;
allocation(Header,i,length_p);
}
printf("当前内存分配情况:\n");
t=Header;
while(t!=0)
{
printf("process name %d,address=%d,length=%d,flag=%d\n", t->name, t->address, t->length,t->flag);
t=t->next;
}
printf("请输入回收的进程号(输入0结束):\n");
scanf("%d",&processname);
while(processname!=0)
{
printf("回收process name %d\n",processname);
reclaim(processname,Header);
printf("当前内存分配情况:\n");
t=Header;
while(t!=0)
{
printf("process name %d,address=%d,length=%d,flag=%d\n", t->name, t->address, t->length,t->flag);
t=t->next;
}//显示当前内存分配情况
if (Header->next==NULL) break;
printf("请输入回收的进程号(输入0结束):\n");
scanf("%d",&processname);
}
printf("当前内存分配情况:\n");
t=Header;
while(t!=0)
{
printf("process name %d,address=%d,length=%d,flag=%d\n", t->name, t->address, t->length,t->flag);
t=t->next;
}
}
运行结果:
四、实验分析与总结
对实验运行结果进行分析:程序采用的是何种动态分区分配算法,写出判断依据,并分析该算法的优缺点。
分析:程序使用一个链表来模拟内存存储空间,以地址递增的顺序链接,采用的是首次适应算法。
该算法倾向于优先利用内存中低地址部分的空闲分区,保留了高地址部分的大空闲分区,为后来的大作业分配大内存创造了条件;其缺点是低地址部分被不断划分,留下了许多小的空闲分区,而每次查找又是从低地址部分开始的,从而增加了查找可用空闲分区时的开销。
总结:这次的实验,使我对动态分区分配算法有了初步的认识和
了解,并能够根据算法的优缺点、进程的需要来选择合适的算法。
在
编写代码的过程中,我还遇到了一些小的问题;比如,对链表进行操作时,老是出现错误,不能对链表进行正确的操作等;这些问题与我对链表的认识不够深入和准确有关,不过,通过这次程序的编写,进一步加深了我对链表的理解,对链表的运用也变得得心应手了。