实验三 分页存储管理
一、实验目的
一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的
主存储器,而且要能合理地分配和使用这些存储空间。当用户提出申请存储器空
间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,
找出足够的空闲区域分配给申请者。当作业撤离或主动归还主存资源时,则存储
管理要收回作业占用的主存空间或归还部分主存空间。主存的分配和回收的实现
虽与主存储器的管理方式有关的,通过本实验理解在不同的存储管理方式下应怎
样实现主存空间的分配和回收。
在计算机系统中,为了提高主存利用率,往往把辅助存储器(如磁盘)作为
主存储器的扩充,使多道运行的作业的全部逻辑地址空间总和可以超出主存的绝
对地址空间。用这种办法扩充的主存储器称为虚拟存储器。通过本实验理解在分
页式存储管理中怎样实现虚拟存储器。
在本实验中,通过编写和调试存储管理的模拟程序以加深对存储管理方案的理
解。熟悉虚存管理的各种页面淘汰算法通过编写和调试地址转换过程的模拟程序
以加强对地址转换过程的了解。
二、实验题目
设计一个可变式分区分配的存储管理方案。并模拟实现分区的分配和回收过
程。
三.实验环境
Win XP,VC++ 6.0
四、实验分析:
1.算法分析:
本次实验中采用的算法是最佳适应算法。
最佳适应算法将可利用空间表中一个大小不小于“请求”且最接近“请求”
的空闲块的一部分分配给用户。分配与回收都需要对可利用空间表从头至尾查询
一遍。为了避免每次分配都要查询整个链表,通常要求节点从大到小排序,由此
只需找到第一个足够大的空闲块即可予以分配。但回收时,必须把回收的空闲块
放置在符合大小顺序关系的链表位置。在分配时容易产生太小而无法利用的内存
碎片,同时这种做法也保留了那些很大的内存块以备响应将来发生的内存量较大
的用户“请求”,从而使整个链表逐渐趋向于节点大小差别甚远的状态。这种分
配算法适合请求分配内存大小范围较广的系统,此算法比较费时间。
2.流程图:
最佳适应算法流程图如下:
3.源程序:
#include
#include
#define MAX 32767
typedef struct node
{
int address,size;
struct node *next;
//设置分区
}RECT;
//函数原型
RECT *assignment(RECT *head,int application);
void acceptment1(RECT *head,RECT *back1);
void acceptment2(RECT *head,RECT *back1) ;
int backcheck(RECT *head,RECT *back1);
void print(RECT *head);
//变量声明
RECT *head,*back,*assign1,*p;
int application1,maxblocknum;
char way;
//主函数
main()
{
char choose[10];
int check;
head=malloc(sizeof(RECT)); //建立可利用区表的初始状态
p=malloc(sizeof(RECT));
head->size=MAX;
head->address=0;
head->next=p;
maxblocknum=1;
p->size=MAX;
p->address=0;
p->next=NULL;
print(head);
//输出可利用表初始状态
do{
printf("申请空间还是回收空间?(as/ac)\n");
scanf("%s",choose); //选择分配或回收
if(strcmp(choose,"as")==0) //as 为分配
{
printf("输入申请空间大小:\n");
scanf("%d",&application1);//输入申请空间大小
assign1=assignment(head,application1);//调用分配函数
if(assign1->address==-1)//分配不成功
printf("申请的空间太大!申请失败!\n\n");
else
printf("申请成功!\n");
printf("分配后分区地址=%5d\n",assign1->address); //分配成
功
print(head); //输出
}
else
if(strcmp(choose,"ac")==0) //回收
{
back=malloc(sizeof(RECT));
printf("输入回收地址和作业大小!!\n");
scanf("%d%d",&back->address,&back->size);//输入回收地址和
大小
check=backcheck(head,back); //检查
acceptment2(head,back);//最佳适应
print(head);
}
}while(!strcmp(choose,"as")||!strcmp(choose,"ac"));
}
//分配函数
RECT *assignment(RECT *head,int application)
{
RECT *after,*before,*assign;
assign=malloc(sizeof(RECT)); //分配申请空间
assign->size=application;
assign->next=NULL;
if(application>head->size||application<=0)
assign->address=-1; //申请无效
else
{
before=head;
after=head->next;
while(after->size
next;
after=after->next;
}
if(after->size==application) //结点大小等于申请大小则完全分配
{
if(after->size==head->size)
maxblocknum--;
before->next=after->next;
assign->address=after->address;
free(after);
}
else
{
if(after->size==head->size) maxblocknum--;
after->size=after->size-application; //大于申请空间则截取相
应大小分配
assign->address=after->address+after->size;
if(tolower(way)=='b')//如果是最佳适应,将截取后剩余结点重新回
收到合适位置
{
}
before->next=after->next;
back=after;
acceptment2(head,back);
}
if(maxblocknum==0) //修改最大数和头结点值
{
before=head;
head->size=0;
maxblocknum=1;
while(before!=NULL)
{
if(before->size>head->size)
{
head->size=before->size;
maxblocknum=1;
}
else
if(before->size==head->size)
maxblocknum++;
before=before->next;
}
}
}
assign1=assign;
return assign1; //返回分配给用户的地址
}
//最佳适应,back1 为回收结点的地址
void acceptment2(RECT *head,RECT *back1)
{
RECT *before,*after;
int insert ;
insert=0;
before=head;
after=head->next;
if(head->next==NULL) //如果可利用区表为空
{
head->size=back1->size;
head->next=back1;
maxblocknum++;
back1->next=NULL;
}
else
{
while(after!=NULL) //与上一块合并
if(back1->address==after->size+after->address)
{
before->next=after->next;
back->size=after->size+back1->size;
free(after);
after=NULL;
}
else
{
after=after->next;
before=before->next;
}
before=head;
after=head->next;
while(after!=NULL)
if(after->address==back1->size+back1->address) //与下一块合并
{
back1->size=back1->size+after->size;
before->next=after->next;
free(after);
after=NULL;
}
else
{
before=before->next;
after=after->next;
}
before=head;//将回收结点插入到合适的位置
after=head->next;
do{
if(after==NULL||(after->size>back1->size))
{
before->next=back1;
back1->next=after;
insert=1;
}
else
{
before=before->next;
after=after->next;
}
}while(!insert);
if(head->sizesize) //修改最大块值和最大块数
{
head->size=back1->size;
maxblocknum++;
}
else
if(head->size==back1->size)
maxblocknum++;
}
}
void print(RECT *head) //输出链表
{
RECT *before,*after;
int index,k;
before=head->next;
index=1;
if(head->next==NULL)
printf("没有空间分配了!\n");
else
{
printf("*****分区*******首地址********尾地址*********分区地址大
小*****\n");
while(before!=NULL)
{
printf("----------------------------------------------------\n");
printf("
dress+before->size-1,before->size);
%-13d%-13d%-13d%-13d\n",index,before->address,before->ad
printf("----------------------------------------------------\n");
index++;
before=before->next;
}
}
}
//检查回收块的合法性,back1 为要回收的结点地址
int backcheck(RECT *head,RECT *back1)
{
RECT *before,*after;
int check=1;
if(back1->address<0||back1->size<0)
check=0;//地址和大小不能为负
before=head->next;
while((before!=NULL)&&check)//地址不能和空闲区表中结点出现重叠
if(((back1->addressaddress)
&&(back1->address+back1->size>before->address))
||((back1->address>=before->address)
&&(back1->addressaddress+before->size)))
check=0;
else
before=before->next;