实验五动态分区存储管理模拟

合集下载

动态分区管理实验报告

动态分区管理实验报告

实验五动态分区管理模拟实验报告关键问题:写一动态分区管理程序,使其内存分配采用最优适应分配算法。

设计思路:在空闲分区链中找最适合的空闲块,使内存碎片尽量的减少!根据最佳适应算法原理,在内存分配函数ffallocation()中,增加记录适合空白块的标记sp,然后拿当前空白块fp减去后jl的后的大小和它后面的另一空白块sp减去jl的大小相比较。

如果前者大于后者,且后者的空白区大于jl的大小,则当前空白块为sp,否则继续往后比较,直到空闲分区链末尾!则当前空白块为最适合的空白块!然后就把当前空白块分配给作业。

其他部分的代码与实例相同!实现的关键代码://------------------------------------------------------------------- //有两个链:空白块链及作业链.空白块链描述空白块,链首指针freep,初始为一大块空白块.//作业链按从高址到低址的顺序链接,链首指针jobp//为作业jn分配jl大小内存,起始地址为javoid ffallocation(int jl,char jn[10],int* ja){mat* jp=NULL;//作业链当前节点mat* jp2=NULL;//新的作业节点mat* jp1=NULL;//freearea* fp=NULL;//当前空白块//修改部分 freearea* sp;//记录适合的空白块int i;*ja=-1;if (totalfree<jl) //剩余空间大小不能满足作业要求return;*ja=0;fp=freep;//取空白块链首块,将顺着链寻找第一块满足作业要求的块。

sp=freep;while (fp!=NULL){if (fp->freesize<jl){fp=fp->next;//当前空白块大小不满足要求sp=sp->next;}else //将当前空白块分配给作业{/*当当前空白块fp与它的下一块空白块sp相比较,如果它减去jl后大于下一空白块sp减去jl,且下一空白块sp大于等于jl,则当前空白块为sp;否则sp继续往后查找,直到空闲块查找完毕,然后当前空闲块为所要查找的适合空闲块!*/while(sp!=NULL){if((fp->freesize-jl>sp->freesize-jl)&(sp->freesize>=jl)){fp=sp;}else{sp=sp->next;}}// jobnumber++;totalfree=totalfree-jl;jp2=new mat;//申请一块作业节点空间//在节点上登记为该作业分配的内存空间// for (i=0;i<10;i++) (jp2->jobname)[i]=' ';i=-1;while(jn[++i])(jp2->jobname)[i]=jn[i];(jp2->jobname)[i]='\0';jp2->joblength=jl;jp2->jobaddress=fp->freeaddress;//登记该作业的起始地址*ja=jp2->jobaddress;//将节点jp2插入作业链jobp,按高址到低址的顺序。

存储管理——动态分区分配回收算法的模拟

存储管理——动态分区分配回收算法的模拟

齐齐哈尔大学操作系统课程综合实践题目:存储管理——动态分区分配/回收算法的模拟班级:0姓名:0学号:0指导教师:02011年 12 月综合实践评分表班级0 姓名0 指导教师0 题目:存储管理---动态分区分配/回收算法的模拟评分标准评分标准分数权重评分的依据得分A C选题10 选题符合大纲要求,题目较新颖,工作量大选题基本符合大纲要求,工作量适中工作态度10 态度端正,能主动认真完成各个环节的工作,不迟到早退,出勤好。

能够完成各环节基本工作,出勤较好。

存储结构、算法描述20能正确选择存储结构,定义准确,算法流程图或类C语言描述的算法准确无误能正确选择存储结构,算法流程图或类C语言描述的算法基本准确独立解决问题的能力10具有独立分析、解决问题能力,有一定的创造性,能够独立完成软件的设计与调试工作,程序结构清晰,逻辑严谨,功能完善。

有一定的分析、解决问题能力。

能够在老师指导下完成软件的设计与调试工作,程序功能较完善。

答辨问题回答20 能准确回答老师提出的问题能基本准确回答老师提出的问题程序运行情况10 程序运行正确、界面清晰,测试数据设计合理。

程序运行正确、界面较清晰,能给出合适的测试数据。

综合实践报告20 格式规范,层次清晰,设计思想明确,解决问题方法合理,体会深刻。

格式较规范,设计思想基本明确,解决问题方法较合理。

总分指导教师(签字):注:介于A和C之间为B级,低于C为D级和E级。

按各项指标打分后,总分在90~100为优,80~89为良,70~79为中,60~69为及格,60分以下为不及格。

存储管理---动态分区分配/回收算法的模拟摘要:主存的分配和回收的实现是与住存储器的管理方式有关的。

解决多进程如何共享主存空间的问题。

当进程运行完时将进程所占的主存空间归还给系统。

可变分区存储管理方式,分区分配中所用的数据就够采用空闲分区说明表和空闲分区链表来进行。

关键字:内存分配,空闲分区表,进程申请队列一、【实践目的】:1、熟悉主存分配与回收2、理解在不同的存储管理方式,如何实现主存空间的分配与回收3、掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方式及其实现过程。

动态分区分配方式的模拟实验原理说明

动态分区分配方式的模拟实验原理说明

动态分区分配方式的模拟实验原理说明一、引言动态分区分配方式是操作系统中的一种内存管理方式,它将内存分为若干个不同大小的分区,根据进程的需求动态地分配内存。

在实际应用中,动态分区分配方式广泛应用于多任务操作系统中,如Windows、Linux等。

本文将介绍动态分区分配方式的模拟实验原理。

二、动态分区分配方式的基本原理动态分区分配方式是指在内存空间中按照进程需要划分出若干个不同大小的空间块,每个空间块可以被一个进程占用。

当有新进程需要内存时,操作系统会在空闲的空间块中选择一个大小合适的空间块给该进程使用。

当进程结束时,该进程所占用的空间块就会被释放出来,成为空闲块。

三、模拟实验环境搭建为了模拟动态分区分配方式,我们需要搭建一个虚拟机环境。

首先需要安装一款虚拟机软件(如VMware Workstation),然后安装一个操作系统(如Windows)。

接下来,在虚拟机中安装Visual Studio等开发工具。

四、模拟实验步骤1.设计数据结构为了方便管理内存空间,我们需要设计一种数据结构来存储内存块的信息。

我们可以使用链表来实现这一功能,每个节点表示一个内存块,包括该内存块的起始地址、大小以及状态(已分配或未分配)等信息。

2.初始化内存空间在模拟实验中,我们需要初始化一段虚拟内存空间。

我们可以使用一个数组来表示整个内存空间,并将其划分为若干个大小不同的空间块。

同时,我们需要将这些空间块的信息存储到链表中。

3.模拟进程请求内存在模拟实验中,我们需要模拟多个进程同时请求内存的情况。

当一个进程请求内存时,操作系统会根据其所需的内存大小,在空闲的空间块中选择一个合适的块分配给该进程,并将该块标记为已分配状态。

4.模拟进程释放内存当一个进程结束时,它所占用的内存块就会被释放出来,成为空闲块。

此时操作系统会更新链表信息,并将该块标记为未分配状态。

5.显示当前内存使用情况在模拟实验过程中,我们需要不断地显示当前的内存使用情况。

实验五 存储管理(实验报告格式)

实验五 存储管理(实验报告格式)

实验五:存储管理一、实验目的(1)熟悉内存空闲分区的分配方式;(2)理解动态分区存储管理方式;(3)掌握动态分区的分配与回收的过程。

二、实验环境微型计算机,Ubuntu Linux10.04 ,gedit,gcc三、实验内容根据流程图和参考程序,完成模拟内存分配和回收过程。

内存空间大小为100,进程数为5,每个进程所需空间为随机产生,大小为1~20,编制程序,首先对5个进程进行内存分配,然后回收指定的进程空间,并进行适当的空闲分区合并操作,要求每次操作结束后都能显示当前的内存分配情况。

四、实验结果截图一截图二截图三五、源代码#include<stdio.h>#include<malloc.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; //不可切割的分区阈值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;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+1;i++){length_p=rand()%20+1; //随机产生进程所需存储空间,至少为1allocation(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;}。

动态分区管理的主存分配模拟设计--最先适应法、最优适应法

动态分区管理的主存分配模拟设计--最先适应法、最优适应法

课程设计题目动态分区管理的主存分配模拟设计--最先适应法、最优适应法学院计算机科学与技术学院专业计算机科学与技术专业班级姓名指导教师2011 年01 月18 日课程设计任务书学生姓名:专业班级:计算机指导教师:工作单位:计算机科学与技术学院题目: 动态分区管理的主存分配模拟设计--最先适应法、最优适应法初始条件:1.预备内容:阅读操作系统的内存管理章节内容,理解动态分区的思想,并体会各分配算法的具体实施方法。

2.实践准备:掌握一种计算机高级语言的使用。

要求完成的主要任务:(包括课程设计工作量及其技术要求,以及说明书撰写等具体要求)1.采用指定算法模拟动态分区管理方式的主存分配。

能够处理以下的情形:⑴随机出现的进程i申请jKB内存,程序能判断是否能分配,如果能分配,要求输出分配的首地址Faddress,并要求输出内存使用情况和空闲情况。

内存情况输出的格式为:Faddress该分区的首地址;Eaddress该分区的尾地址Len 分区长度;Process 如果使用,使用的进程号,否则为0⑵主存分配函数实现寻找空闲区、空闲区表的修改、已分配区表的修改功能;2.设计报告内容应说明:⑴课程设计目的与功能;⑵需求分析,数据结构或模块说明(功能与框图);⑶源程序的主要部分;⑷运行结果与运行情况分析;⑸自我评价与总结:i)你认为你完成的设计哪些地方做得比较好或比较出色;ii)什么地方做得不太好,以后如何改正;iii)从本设计得到的收获(在编写,调试,执行过程中的经验和教训);iv)完成本题是否有其他的其他方法(如果有,简要说明该方法);v)对实验题的评价和改进意见,请你推荐设计题目。

时间安排:设计安排一周:周1、周2:完成程序分析及设计。

周2、周3:完成程序调试及测试。

周4、周5:验收、撰写课程设计报告。

(注意事项:严禁抄袭,一旦发现,抄与被抄的一律按0分记)指导教师签名:年月日系主任(或责任教师)签名:年月日动态分区管理的主存分配模拟设计--最先适应法、最优适应法1.目的与功能采用指定算法模拟动态分区管理方式的主存分配。

实验五动态分区分配算法的模拟

实验五动态分区分配算法的模拟

实验五动态分区分配算法的模拟为了更好地理解动态分区分配算法的工作原理,我们可以进行一次模拟实验。

在实验中,我们将模拟一个内存分区,并使用动态分区分配算法来管理这些分区。

首先,让我们定义一个内存大小为1000字节的分区。

我们假设这个内存中包含几个已分配的分区和几个空闲的分区。

我们使用首次适应算法来进行分区的首次适应分配。

首先,我们将整个内存空间标记为空闲状态,并创建一个初始的空闲链表。

我们假设初始时只有一个空闲分区,大小为1000字节,起始地址为0。

现在,假设有一个进程请求分配一个250字节大小的内存空间。

我们首先检查空闲链表,找到一个大小大于等于250字节的空闲分区。

在这种情况下,我们发现第一个空闲分区的大小是1000字节,所以我们将它拆分成250字节的已分配分区和750字节的空闲分区。

我们在已分配分区上标记一个进程编号,并将空闲分区加入空闲链表。

接下来,假设我们的进程需要申请500字节的内存空间。

在这种情况下,我们需要查找一个大小大于等于500字节的空闲分区。

我们发现第一个可用的空闲分区大小是750字节,我们将它拆分为已分配的500字节和剩余的250字节的空闲分区。

然后,我们假设有进程释放了先前分配的250字节的内存空间。

当一个进程释放分配的内存空间时,我们需要合并相邻的空闲分区。

在这种情况下,释放的分区位于地址0,大小为250字节,并且其下一个分区是地址500,大小为500字节的空闲分区。

因此,我们将这两个分区合并为一个大小为750字节的空闲分区。

接下来,我们假设另一个进程将请求600字节的内存空间。

根据首次适应算法,我们将在第一个满足条件的空闲分区进行分配。

在这种情况下,我们将分配200字节的空闲分区和分配400字节的空闲分区拆分为600字节的已分配分区和空闲分区。

最后,假设一个进程请求200字节的内存空间。

根据首次适应算法,我们在第一个满足条件的空闲分区进行分配。

在这种情况下,我们将250字节的空闲分区拆分为200字节的已分配分区和50字节的空闲分区。

实验五 动态分区分配算法的模拟

实验五 动态分区分配算法的模拟

实验五动态分区分配算法的模拟一、实验目的1、加深操作系统内存管理过程的理解2、掌握内存分配算法的基本应用二、实验任务请同学们用C/C++实现一个完整的(可变)动态分区管理器,包括分配,回收,分区碎片整理等。

希望同学们实现如下功能:n 初始化功能:内存状态设置为初始状态。

n 分配功能:要求至少使用两种算法,用户可以选择使用。

n 回收功能:n 空闲块的合并:即紧凑功能,用以消除碎片。

当做碎片整理时,需要跟踪分配的空间,修改其引用以保证引用的正确性。

n 显示当前内存的使用状态,可以使用表格或图形。

三、实验指导1.基本思想动态分区是指系统不预先划分固定分区,而是在装入程序的时候划分内存区域,使得为程序分配的分区大小恰好等于该程序的需求量,且分区的个数是动态的。

显然动态分区有较大的灵活性,较之固定分区能获得好的内存利用率。

2.数据结构动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。

另一种也是最常用的就是空闲链表,由于对分区的操作是动态的,所以很难估计数据结构所占用的空间,而且空闲区表会占用宝贵的系统空间,所以提出了空闲链表的概念。

其特点是用于管理分区的信息动态生成并和该分区在物理地址上相邻。

这样由于可以简单用两个空闲块之间的距离定位已分配空间,不仅节约了系统空间,而且不必维持已分配空间的信息。

本实验是要做一个模拟程序,来模拟动态分区算法的分配和回收过程,并不是真正的去分配和回收内存。

基本的模拟方法有两种:1、先从内存中申请一块存储区,对这块存储区进行模拟的分配和回收活动。

2、不申请存储区,自己定义一块虚拟的存储区,对这块存储区进行模拟的分配和回收活动,分配和回收仅仅是对数据结构的修改而已。

程序代码:#include<iostream>using namespace std;int FreePartition[100];//空闲分区块数组int FirstPartition[100];//首次适应算法数组int CycleFirstPartition[100];//循环首次适应算法数组int BestPartition[100];//最佳适应算法数组int WorstPartition[100];//最坏适应算法数组int ProcessNeed[100];//每个作业的大小int PartitionNum,ProcessNum;//分区块数,作业数//首次适应算法void First(){int i,j;char str;for(i=0;i<PartitionNum;i++){FirstPartition[i]=FreePartition[i];}for(i=0;i<ProcessNum;i++)//找出第一块满足作业的分区for(j=0;j<PartitionNum;j++){if(ProcessNeed[i]>FirstPartition[j])continue;else{FirstPartition[j]-=ProcessNeed[i];//找到后把分区大小减去作业的大小 ? ? ? ? ? ? ?str='A'+i;cout<<"作业"<<str<<"在第"<<j+1<<"块分区中"<<endl;break;}}cout<<endl;cout<<"分配之后剩余情况:"<<endl;?for(i=0;i<PartitionNum;i++)cout<<FirstPartition[i]<<" ";cout<<endl<<endl;}//循环首次适应算法void CycleFirst(){int i,j=1;char str;for(i=0;i<PartitionNum;i++){CycleFirstPartition[i]=FreePartition[i];}for(i=0;i<ProcessNum;i++)//for(j=0;j<PartitionNum;j++){j=j-1;while(j<PartitionNum)if(ProcessNeed[i]>CycleFirstPartition[j])//continue;j++;else{CycleFirstPartition[j]-=ProcessNeed[i];str='A'+i;cout<<"作业"<<str<<"在第"<<j+1<<"块分区中"<<endl; break;}//j++;//cout<<j<<" ";if(j==PartitionNum && i!=ProcessNum){i=-1;}}}cout<<endl;cout<<"分配之后剩余情况:"<<endl;for(i=0;i<PartitionNum;i++)cout<<CycleFirstPartition[i]<<" ";cout<<endl<<endl;}//最佳适应算法void Best(){int i,j,k;char str;?for(i=0;i<PartitionNum;i++){BestPartition[i]=FreePartition[i];}for(i=0;i<ProcessNum;i++){k=0;for(j=0;j<PartitionNum;j++){//cout<<BestPartition[j]<<" ? "<<ProcessNeed[i]<<endl; if(BestPartition[j]>=ProcessNeed[i]){break;}}for(int n=0;n<PartitionNum;n++){if(BestPartition[n]<BestPartition[k] && BestPartition[n]>=ProcessNeed[i])//找最佳的 k=n;}BestPartition[k]-=ProcessNeed[i];str='A'+i;cout<<"作业"<<str<<"在第"<<j+1<<"块分区中"<<endl;}cout<<endl;cout<<"分配之后剩余情况:"<<endl;for(i=0;i<PartitionNum;i++)cout<<BestPartition[i]<<" ";cout<<endl<<endl;}//最坏适应算法void Worst(){int i,j,k;char str;for(i=0;i<PartitionNum;i++){WorstPartition[i]=FreePartition[i];}for(i=0;i<ProcessNum;i++){k=0;for(j=0;j<PartitionNum;j++){if(WorstPartition[j]>WorstPartition[k])//找到最大的分区k=j;}WorstPartition[k]-=ProcessNeed[i];str='A'+i;cout<<"作业"<<str<<"在第"<<j+1<<"块分区中"<<endl;}cout<<endl;cout<<"分配之后剩余情况:"<<endl;for(i=0;i<PartitionNum;i++)cout<<WorstPartition[i]<<" ";cout<<endl<<endl;}void main(){int i;cout<<"输入分区块数:"<<endl;cin>>PartitionNum;cout<<"输入每个分区的大小:"<<endl;for(i=0;i<PartitionNum;i++)cin>>FreePartition[i];cout<<"输入作业数:"<<endl;cin>>ProcessNum;cout<<"输入每个作业的大小:"<<endl;for(i=0;i<ProcessNum;i++)cin>>ProcessNeed[i];cout<<"------------首次适应算法-----------------"<<endl; First();cout<<"------------循环首次适应算法-------------"<<endl; ?CycleFirst();cout<<"------------最佳适应算法-----------------"<<endl; Best();cout<<"------------最坏适应算法-----------------"<<endl; Worst();}。

计算机操作系统实验报告动态分区分配方式的模拟

计算机操作系统实验报告动态分区分配方式的模拟

计算机操作系统实验报告姓名:班级:学号:题目:动态分区分配方式的模拟实习内容简要描述本次实验要完成两部分内容:一是用C语言实现对采用首次适应算法和最佳适应算法的动态分区分配过程ALLOCo和回收过程FREE(),其中空闲分区由空闲分区链来管理,进行分配时,系统优先使用空闲区底端空间。

二是假设初始状态下,可用内存空间为640KBO按照题目要求的作业顺序,以及各个作业分配和回收的内存空间。

分别采用首次适应法和最佳适应法,对内存进行分配和回收,要求每次分配和回收后显示空闲内存分区链的情况。

实验分析算法介绍本次实验通过用C语言进行编程并调试、运行,形象地表现出动态分区的分配方式,直观地展现了首次适应算法和最佳适应算法对内存的释放和回收方式之间的区别。

加深了我们对两种算法优缺点的理解,帮助我们了解一些数据结构和分配算法,进一步加深我们对动态分区存储器管理方式及其实现过程的理解。

主要的问题在于,如何解决两种算法对内存的释放和回收空间的表示。

动态分区分配:又称为可变分区分配,这种分配方式并不事先先将主存划分成一块块的分区,而是在作业进入主存时,根据作业的大小动态地建立分区。

并使分区的大小正好适应作业的需要。

因此系统中分区的大小是可变的,分区的数目也是可变的。

分区分配算法:(两者的空闲块链接方式不冋)①首次适应法:为作业选择分区时总是按地址从高到低搜索,只要找到可以容纳该作业的空白块,就把该空白块分配给该作业。

特点:优先利用内存中底地址部分的空闲分区(将所有空闲区,按其地址递增的顺序链接)②最佳适应算法:接到内存申请时,在空闲块表中找到一个不小于请求的最小空块进行分配;为作业选择分区时总是寻找其大小最接近于作业所要求的存储区域。

特点:用最小空间满足要求(将所有空闲区,按其大小递增的顺序联接成空闲区链)结果分析(思考题解答;错误原因分析)间的分配和回收。

思考题解答:1、首次适应算法分配时从表头指针开始查找可利用空间表,将找到的第一个大小不小于“请求”的空闲块的一部分分配给用户。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验五动态分区存储管理模拟一、实验目的深入了解可变分区存储管理式主存分配回收的实现。

二、实验预备知识可变分区存储管理式不预先将主存划分成几个区域,而把主存除操作系统占用区域外的空间看作一个大的空闲区。

当进程要求装入主存时,根据进程需要主存空间的大小查询主存各个空闲区,当从主存空间找到一个大于或等于该进程大小要求的主存空闲区时,选择其中一个空闲区,按进程需求量划出一个分区装入该进程。

进程执行完后,它所占的主存分区被回收,成为一个空闲区。

如果该空闲区的相邻分区也是空闲区,则需要将相邻空闲区合并成一个空闲区。

这个实验主要需要考虑三个问题:(1)设计记录主存使用情况的数据表格,用来记录空闲区和进程占用的区域;(2)在设计的数据表格基础上设计主存分配算法;(3)在设计的数据表格基础上设计主存回收算法。

首先,考虑第一个问题:设计记录主存使用情况的数据表格,用来记录空闲区和进程占用的区域。

由于可变分区的大小是由进程需求量决定的,故分区的长度是预先不固定的,且分区的个数也随主存分配和回收而变动。

总之,所有分区情况随时可能发生变化,数据表格的设计必须和这个特点相适应。

由于分区长度不同,因此设计的表格应该包括分区在主存中的起始地址和长度。

由于分配时空闲区有时会变成两个分区:空闲区和已分分区,回收主存分区时,可能会合并空闲分区,这样如果整个主存采用一表格记录已分分区和空闲区,就会使表格操作繁琐。

主存分配时查找空闲区进行分配,然后填写已分分区表,主要操作在空闲区;某个进程执行完成后,将该分区变成空闲区,并将其与相邻空闲区合并,主要操作也在空闲区。

由此可见,主存分配和回收主要是对空闲区的操作。

这样,为了便于对主存空间的分配和回收,就建立两分区表记录主存使用情况,一表格记录进程占用分区的“已分分区表”;一是记录空闲区的“空闲区表”。

这两表的实现法一般有两种,一种是链表形式,一种是顺序表形式。

在实验中,采用顺序表形式,用数组模拟。

由于顺序表的长度必须提前固定,所以无论是“已分分区表”还是“空闲区表”都必须事先确定长度。

它们的长度必须是系统可能的最大项数,系统运行过程中才不会出错,因而在多数情况下,无论是“已分分区表”还是“空闲区表”都有空闲栏目。

已分分区表中除了分区起始地址、长度外,也至少还要有一项“标志”,如果是空闲栏目,容为“空”,如果为某个进程占用分区的登记项,容为该进程的进程名;空闲区表中除了分区起始地址、长度外,也要有一项“标志”,如果是空闲栏目,容为“空”,如果为某个空闲区的登记项,容为“未分配”。

在实际系统中,这两个表格的容可能还要更多,实验中仅仅使用上述必须的数据。

为此,“已分分区表”和“空闲区表”在实验中有如下的结构定义:已分分区表的定义:#define n 10 //假定系统允的进程数量最多为nstruct{float address; //已分分区起始地址float length; //已分分区长度,单位为字节int flag; //已分分区表登记栏标志,“0”表示空栏目,实验中只支持一个字符的进程名}used_table[n]; //已分分区表空闲区表的定义:#define m 10 //假定系统允的空闲区数量最多为mstruct{float address; //空闲区起始地址float length; //空闲区长度,单位为字节int flag; //空闲区表登记栏标志,“0”表示空栏目,用“1”表示未分配}free_table[m]; //空闲区表其中分区起始地址和长度数值太大,超出了整型的表达围,所以采用了float 类型。

然后,就要考虑如在设计的数据表格上进行主存的分配。

当要装入一个进程时,从空闲区表中查找标志为“未分配”的空闲区,从中找到一个能容纳该进程的空闲区。

如果找到的空闲区正好等于该进程的长度,则把该分区全部分配给进程。

这时应该把该空闲区登记栏中的标志改为“空”,同时在已分分区表中找到一个标志为“空”的栏目登记新装入进程所占用分区的起始地址、长度和进程名。

如果找到的空闲区大于进程长度,则把空闲区分成两部分,一部分用来装入进程,另外一部分仍为空闲区。

这时只要修改元空闲区的长度,且把新装入的进程登记到已分分区表中。

实验示例程序中主存分配算法采用最佳适应算法。

最佳适应算法是按进程要求挑选一个能满足进程要求的最小空闲区,这样保证可以不去分割一个大的区域,使装入大进程时比较容易得到满足。

但是最佳适应算法容易出现找到的一个分区可能只比进程所要求的长度略大一点的情况,这时,空闲区分割后剩下的空闲区就很小,这种很小的空闲区往往无法使用,影响了主存的使用。

为了一定程度上解决这个问题,如果空闲区的大小比进程要求的长度略大一点,不再将空闲区分成空闲区和已分分区两部分,而是将整个空闲区分配给进程。

在实现最佳适应算法时,可把空闲区按长度以递增式登记在空闲区中。

分配时顺序查找空闲表,查找到的第一个空闲区就是满足进程要求的最小分区。

这样查找速度快,但是为使空闲区按长度以递增顺序登记在空闲分区表中,就必须在分配回收时进行空闲区表的调整。

空闲区表调整时移动表目的代价要高于查询整表的代价,所以实验中不采用空闲区有序登记在空闲表中的法。

动态分区式的主存分配流程图如图5-1所示。

图5-1 动态分区最佳分配算法流程图最后,是可变分区式下的主存回收问题。

可变分区式下回收主存空间时,应该检查是否有与归还区相邻的空闲区。

若有,则应该合并成一个空闲区。

一个归还区可能有上邻空闲区,也可能有下邻空闲区,或者既有上邻空闲区又有下邻空闲区,或者既无上邻空闲区又无下邻空闲区。

在实现回收时,首先,将进程归还的区域在已分分区表中找到,将该栏目的状态变为“空”;然后,检查空闲区表中标志为“未分配”的栏目,查找是否有相邻空闲区;最后,合并空闲区,修改空闲区表。

假定进程归还得分区起始地址为S,长度为L,则:(1)归还区有下邻空闲区如果S+L正好等于空闲区表中某个登记栏目(假定为第j栏)的起始地址,则表明归还区有一个下邻空闲区。

这时只要修改第j栏登记项的容:起始地址=S;第j栏长度=第j栏长度+L;则第j栏指示的空闲区是归还区和下邻空闲区合并后的大空闲区。

(2)归还区有上邻空闲区如果空闲区表中某个登记栏目(假定为第k栏)的“起始地址+长度” 正好等于S,则表明归还区有一个上邻空闲区。

这时要修改第k栏登记项的容(起始地址不变):第k栏长度=第k栏长度+L;则第k栏指示的空闲区是归还区和上邻空闲区合并后的大空闲区。

(3)归还区既有上邻空闲区又有下邻空闲区如果S+L正好等于空闲区表中某个登记栏目(假定为第j栏)的起始地址,同时还有某个登记栏目(假定为第k栏)的“起始地址+长度” 正好等于S,这表明归还区既有一个上邻空闲区,又有一个下邻空闲区。

这时对空闲区表的修改如下:第k栏长度=第k栏长度+第j栏长度+L;(第k栏起始地址不变)第j栏状态=“空”;(将第j栏登记项删除)则第k栏指示的空闲区是归还区和上、下邻空闲区合并后的大空闲区;原来的下邻空闲区登记项(第j栏)被删除,置为“空”。

(4)归还区既无上邻空闲区又无下邻空闲区如果在检查空闲区表时,无上述三种情况出现,则表明归还区既无上邻空闲区又无下邻空闲区。

这时,应该在空闲区表中查找一个状态为“空”的栏目(假定查到的是第t栏),则第t栏的容修改如下:第t栏起始地址=S;第t栏长度=L;第t栏状态=“未分配”这样,第t栏指示的空闲区是归还区。

按上述法归还主存区域的流程图如图5-2所示。

由于是模拟实验,没有真正的主存要分配,所以在实验中:首先,应建立一空闲区表,初始状态只有一个空闲登记项(假定的主存空闲区)和一所有状态都为“空”的已分分区表,假定主存空间为110KB,操作系统占用10KB,其余为空闲区;然后,可以选择进行主存分配或主存回收,如果是分配,要求输入进程名和所需主存空间大小,如果是回收,输入回收进程的进程名,循环进行主存分配和回收后,如果需要,则显示两表的容,以检查主存的分配和回收是否正确。

三、实验容编写程序完成可变分区存储管理式的主存分配回收的实现。

在已给参考示例程序的基础上,完成如下任务:(1)采用链表形式的主存分区空闲表;(2)采用首次适应算法、循环首次适应算法、最差适应算法完成主存空间的分配和回收;(3)编写主函数对所做工作进行测试。

参考程序#define n 10 //假定系统允的进程数量最多为n#define m 10 //假定系统允的空闲区数量最多为m#define minisize 100struct{float address; //已分分区起始地址float length; //已分分区长度,单位为字节int flag; //已分分区表登记栏标志,“0”表示空栏目,实验中只支持一个字符的进程名}used_table[n]; //已分分区表struct{float address; //空闲区起始地址float length; //空闲区长度,单位为字节int flag; //空闲区表登记栏标志,“0”表示空栏目,用“1”表示未分配}free_table[m]; //空闲区表allocate(char P , float xk) //采用最佳适应算法为进程P分配xk大小的主存空间{int i, k;float ad;k= -1;for(i=0; i<m; i++) //寻找主存空间于xk的最小空闲区登记项kif(free_table[i].length>=xk && free_table[i].flag==1)if(k== -1 || free_table[i].length<free_table[k].length)k=i;if(k== -1) //未找到可用空闲区,返回{ printf(“无可用空闲区\n”);return;}//找到可用空闲区,开始分配:若空闲区大小与要求分配的空间差小于或等于minisize,则空闲区全部分配;若空闲区大小与要求分配的空间差大于minisize,则从空闲区划出一部分分配if(free_table[k].length-xk<=minisize){free_table[k].flag=0;ad=free_table[k].address;xk= free_table[k].length;}else{free_table[k].length= free_table[k].length-xk;ad= free_table[k].address+ free_table[k].length;}//修改已分分区表i=0;while(used_table[i].flag!=0 && i<n) //寻找空表目i++;if(i>=n) //无表目填写已分分区{printf(“无表目填写已分分区,错误!\n”);//修正空闲区表if(free_table[k].flag==0) //前面找到的是整个空闲区free_table[k].flag=1;else //前面找到的是某个空闲区的一部分free_table[k].length= free_table[k].length+xk;return;}else //修改已分分区表{used_table[i]. address=ad;used_table[i]. length=xk;used_table[i].flag=J;}return;}//主存分配函数结束reclaim(char P) //回收进程名为P的进程所占的主存空间{int i,k,j,s,t;float S,L;//寻找已分分区表中对应登记项s=0;while((used_table[s].flag!=P || used_table[s].flag==0) && s<n)s++;if(s>=n) //已分分区表中找不到名为P的进程,返回{printf(“找不到该进程\n”);return;}//修改已分分区表used_table[s].flag=0;//取得归还分区的起始地址S和长度LS= used_table[s]. address;L= used_table[s]. length;j=-1;k=-1;i=0;//寻找归还分区的上下邻空闲区,上邻表目k,下邻表目jwhile(i<m && (j==-1 || k==-1)){if(free_table[i].flag==0){if(free_table[i].address+ free_table[i].length==S) //找到上邻k=i;if(free_table[i].address==S+L) //找到下邻j=i;}}if(k!=-1)if(j!=-1) //与上下邻空闲区三项合并{free_table[k].length= free_table[j].length+ free_table[k].length+L;free_table[i].flag=0;}else //上邻空闲区,下邻非空闲区,与上邻合并free_table[k].length= free_table[k].length+L;elseif(j!=-1){free_table[j]. address=S;free_table[j].length= free_table[j].length+L;}else{t=0;while(free_table[t].flag==1 && t<m)t++;if(t>m)printf(“空闲区表没有空间,回收空间失败!\n”);used_table[s].flag=J;return;}free_table[t]. address=S;free_table[t].flag==1;free_table[t].length=L;}return(true);}//主存回收函数结束。

相关文档
最新文档