广工 操作系统课程设计 最佳适应算法、最坏适应算法、循环首次适应算法

合集下载

首次适应算法和循环首次适应算法

首次适应算法和循环首次适应算法

首次适应算法和循环首次适应算法一、实验目的1、加深操作系统内存管理过程的理解2、掌握内存分配算法的基本应用二、实验要求1.在分配时,须按照一定的分配算法,从空闲分区表或空闲分区链中选取一分区分配给该作业2.上机时独立完成编辑,调试程序。

三、实验任务请同学们用C/C++实现一个完整的(可变)动态分区管理器,包括分配,回收,分区碎片整理等。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

程序代码:#include<iostream>using namespace std;intFreePartition[100];//空闲分区块数组intFirstPartition[100];//首次适应算法数组intCycleFirstPartition[100];//循环首次适应算法数组intProcessNeed[100];//每个作业的大小intPartitionNum,ProcessNum;//分区块数,作业数//首次适应算法void First(){inti,j;charstr;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;}//循环首次适应算法voidCycleFirst(){inti,j=1;charstr;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 main(){inti;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();六、实验总结在一开始老师布置这次的实验题目时,自己根本不知道要干什么,因为在上课时对动态分区分配这节内容不是太了解,所以在上机时不知道如何下手,后来,将本章内容反复的看了几遍之后,终于有了自己的思路。

首次适应算法,最佳适应算法,最坏适应算法源代码[宝典]

首次适应算法,最佳适应算法,最坏适应算法源代码[宝典]

首次适应算法,最佳适应算法,最坏适应算法源代码[宝典] 首次适应算法,最佳适应算法,最坏适应算法源代码#include<iostream.h> #include<stdlib.h>#define Free 0 //空闲状态 #define Busy 1 //已用状态 #define OK 1 //完成#define ERROR 0 //出错#define MAX_length 640 //最大内存空间为640KBtypedef int Status;int flag;typedef struct freearea//定义一个空闲区说明表结构{long size; //分区大小long address; //分区地址int state; //状态 }ElemType;// 线性表的双向链表存储结构 typedef struct DuLNode {ElemType data;struct DuLNode *prior; //前趋指针struct DuLNode *next; //后继指针 }DuLNode,*DuLinkList;DuLinkList block_first; //头结点 DuLinkList block_last; //尾结点Status alloc(int);//内存分配 Status free(int); //内存回收Status First_fit(int);//首次适应算法Status Best_fit(int); //最佳适应算法 Status Worst_fit(int); //最差适应算法void show();//查看分配Status Initblock();//开创空间表Status Initblock()//开创带头结点的内存空间链表{block_first=(DuLinkList)malloc(sizeof(DuLNode)); block_last=(DuLinkList)malloc(sizeof(DuLNode)); block_first->prior=NULL;block_first->next=block_last;block_last->prior=block_first;block_last->next=NULL;block_last->data.address=0;block_last->data.size=MAX_length;block_last->data.state=Free;return OK;}//分配主存Status alloc(int ch){int request = 0;cout<<"请输入需要分配的主存大小(单位:KB):"; cin>>request;if(request<0 ||request==0){cout<<"分配大小不合适,请重试~"<<endl;return ERROR;}if(ch==2) //选择最佳适应算法{if(Best_fit(request)==OK) cout<<"分配成功~"<<endl; else cout<<"内存不足,分配失败~"<<endl;return OK;}if(ch==3) //选择最差适应算法{if(Worst_fit(request)==OK) cout<<"分配成功~"<<endl; else cout<<"内存不足,分配失败~"<<endl;return OK;}else //默认首次适应算法{if(First_fit(request)==OK) cout<<"分配成功~"<<endl; else cout<<"内存不足,分配失败~"<<endl;return OK;}}//首次适应算法Status First_fit(int request){//为申请作业开辟新空间且初始化DuLinkList temp=(DuLinkList)malloc(sizeof(DuLNode)); temp->data.size=request;temp->data.state=Busy;DuLNode *p=block_first->next;while(p){if(p->data.state==Free && p->data.size==request){//有大小恰好合适的空闲块p->data.state=Busy;return OK;break;}if(p->data.state==Free && p->data.size>request){//有空闲块能满足需求且有剩余temp->prior=p->prior;temp->next=p;temp->data.address=p->data.address;p->prior->next=temp;p->prior=temp;p->data.address=temp->data.address+temp->data.size; p->data.size-=request;return OK;break;}p=p->next;}return ERROR;}//最佳适应算法Status Best_fit(int request){int ch; //记录最小剩余空间DuLinkList temp=(DuLinkList)malloc(sizeof(DuLNode)); temp->data.size=request;temp->data.state=Busy;DuLNode *p=block_first->next;DuLNode *q=NULL; //记录最佳插入位置while(p) //初始化最小空间和最佳位置{if(p->data.state==Free && (p->data.size>=request) ) {if(q==NULL){q=p;ch=p->data.size-request;}else if(q->data.size > p->data.size){q=p;ch=p->data.size-request;}}p=p->next;}if(q==NULL) return ERROR;//没有找到空闲块else if(q->data.size==request){q->data.state=Busy;return OK;}else{temp->prior=q->prior;temp->next=q;temp->data.address=q->data.address;q->prior->next=temp;q->prior=temp;q->data.address+=request;q->data.size=ch;return OK;}return OK;}//最差适应算法Status Worst_fit(int request){int ch; //记录最大剩余空间DuLinkList temp=(DuLinkList)malloc(sizeof(DuLNode)); temp->data.size=request;temp->data.state=Busy;LNode *p=block_first->next; DuDuLNode *q=NULL; //记录最佳插入位置while(p) //初始化最大空间和最佳位置{if(p->data.state==Free && (p->data.size>=request) ) {if(q==NULL){q=p;ch=p->data.size-request;}else if(q->data.size < p->data.size){q=p;ch=p->data.size-request;}}p=p->next;}if(q==NULL) return ERROR;//没有找到空闲块else if(q->data.size==request){q->data.state=Busy;return OK;}else{temp->prior=q->prior;temp->next=q;temp->data.address=q->data.address;q->prior->next=temp;q->prior=temp;q->data.address+=request;q->data.size=ch;return OK;}return OK;}//主存回收Status free(int flag){DuLNode *p=block_first;for(int i= 0; i <= flag; i++)if(p!=NULL)p=p->next;elsereturn ERROR;p->data.state=Free;if(p->prior!=block_first &&p->prior->data.state==Free)//与前面的空闲块相连{p->prior->data.size+=p->data.size;p->prior->next=p->next;p->next->prior=p->prior;p=p->prior;}if(p->next!=block_last && p->next->data.state==Free)// 与后面的空闲块相连{p->data.size+=p->next->data.size;p->next->next->prior=p;p->next=p->next->next;}if(p->next==block_last && p->next->data.state==Free)//与最后的空闲块相连{p->data.size+=p->next->data.size;p->next=NULL;}return OK;}//显示主存分配情况void show(){int flag = 0;cout<<"\n主存分配情况:\n";cout<<"++++++++++++++++++++++++++++++++++++++++++++++\n\n";DuLNode *p=block_first->next;cout<<"分区号\t起始地址\t分区大小\t状态\n\n";while(p){cout<<" "<<flag++<<"\t";cout<<" "<<p->data.address<<"\t\t";cout<<" "<<p->data.size<<"KB\t\t";if(p->data.state==Free) cout<<"空闲\n\n";else cout<<"已分配\n\n";p=p->next;}cout<<"++++++++++++++++++++++++++++++++++++++++++++++\n\n"; }//主函数void main(){int ch;//算法选择标记cout<<"请输入所使用的内存分配算法:\n";cout<<"(1)首次适应算法\n(2)最佳适应算法\n(3)最差适应算法\n"; cin>>ch;while(ch<1||ch>3){cout<<"输入错误,请重新输入所使用的内存分配算法:\n";cin>>ch;}Initblock(); //开创空间表int choice; //操作选择标记while(1){show();cout<<"请输入您的操作:";cout<<"\n1: 分配内存\n2: 回收内存\n0: 退出\n";cin>>choice;if(choice==1) alloc(ch); // 分配内存else if(choice==2) // 内存回收{int flag;cout<<"请输入您要释放的分区号:"; cin>>flag;free(flag);}else if(choice==0) break; //退出else //输入操作有误{cout<<"输入有误,请重试~"<<endl; continue;}}}。

首次适应算法,最佳适应算法,最坏适应算法

首次适应算法,最佳适应算法,最坏适应算法

首次适应算法,最佳适应算法,最坏适应算法首次适应算法、最佳适应算法和最坏适应算法是常见的内存分配算法,也是操作系统中重要的实现方式。

首次适应算法是向空闲区域分配内存时,按照空闲区域的起始地址从小到大进行扫描,找到第一个可以分配的空闲区域,然后将其分配给请求者。

虽然该算法简单易懂,但不断扫描空闲区域会大大降低操作系统的效率。

同时,由于内存释放会产生内存碎片,首次适应算法效果也会逐渐变差。

最佳适应算法是相对于首次适应算法而言的。

它是在空闲区域中寻找最小可用空间,尽可能满足分配请求。

该算法不会一遍遍扫描空闲区域,因此效率更高。

但随着分配请求增多,内存碎片也会不断增加,最佳适应算法将面临“Eureka”陷阱,即为了满足分配请求而不得不“铺平”内存分配空间,导致后续分配请求无法得到满足。

最坏适应算法是在空闲区域中寻找最大可用空间,分配请求时尽可能让内存块留有足够大的空间,防止内存碎片增多。

该算法的效率较低,因为会在所有空闲区域中查找最大空间;但相比较首次适应算法和最佳适应算法,他避免了内存碎片的问题。

总之,以上三种算法都有自己的优点和缺点,为了更好地利用内存资源,可以根据实际情况选择适合的算法。

同时,需要及时对内存进行整理、清理和释放,保证内存的健康状态,提高操作系统的运行效率。

【免费下载】 循环首次适应算法、首次适应算法、最佳适应算法 C语言版

【免费下载】 循环首次适应算法、首次适应算法、最佳适应算法 C语言版
t->size=p->size; t->start=p->start; t->end=p->end;
p->size=size; p->start=start; p->end=end;
t=p->next; p=p->next;
} }// end of BF_SortList
void SortList() /*首次和循环首次适应算法的排序*/ {
//PrintList(); }// end of GetFree
void Assign(int size) /*最佳适应算法和首次适应算法空闲分区的分配*/ {
LN *p,*t; p=L->next; t=L; while(p) {
if(size > p->size) {
p=p->next; t=t->next; if(!p) {
#include<stdio.h>
#define getpch(type) (type*)malloc(sizeof(type))
struct LNode
{ int size;
int start;
int end;
struct LNode *next;
struct LNode *front;
}*L; /*L 为头指针*/
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电,力根通保据过护生管高产线中工敷资艺设料高技试中术卷资,配料不置试仅技卷可术要以是求解指,决机对吊组电顶在气层进设配行备置继进不电行规保空范护载高与中带资负料荷试下卷高问总中题体资,配料而置试且时卷可,调保需控障要试各在验类最;管大对路限设习度备题内进到来行位确调。保整在机使管组其路高在敷中正设资常过料工程试况中卷下,安与要全过加,度强并工看且作护尽下关可都于能可管地以路缩正高小常中故工资障作料高;试中对卷资于连料继接试电管卷保口破护处坏进理范行高围整中,核资或对料者定试对值卷某,弯些审扁异核度常与固高校定中对盒资图位料纸置试,.卷保编工护写况层复进防杂行腐设自跨备动接与处地装理线置,弯高尤曲中其半资要径料避标试免高卷错等调误,试高要方中求案资技,料术编试交写5、卷底重电保。要气护管设设装线备备置敷4高、调动设中电试作技资气高,术料课中并3中试、件资且包卷管中料拒含试路调试绝线验敷试卷动槽方设技作、案技术,管以术来架及避等系免多统不项启必方动要式方高,案中为;资解对料决整试高套卷中启突语动然文过停电程机气中。课高因件中此中资,管料电壁试力薄卷高、电中接气资口设料不备试严进卷等行保问调护题试装,工置合作调理并试利且技用进术管行,线过要敷关求设运电技行力术高保。中护线资装缆料置敷试做设卷到原技准则术确:指灵在导活分。。线对对盒于于处调差,试动当过保不程护同中装电高置压中高回资中路料资交试料叉卷试时技卷,术调应问试采题技用,术金作是属为指隔调发板试电进人机行员一隔,变开需压处要器理在组;事在同前发一掌生线握内槽图部内 纸故,资障强料时电、,回设需路备要须制进同造行时厂外切家部断出电习具源题高高电中中源资资,料料线试试缆卷卷敷试切设验除完报从毕告而,与采要相用进关高行技中检术资查资料和料试检,卷测并主处且要理了保。解护现装场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。

操作系统练习题2

操作系统练习题2

操作系统练习题2一、选择题1.操作系统是计算机系统的核心软件。

按功能特征的不同,可把操作系统分为[1]_________________、[2]___________________、[3]_____________________、网络操作系统和分布式操作系统几种基本类型。

其中[1]的主要目的是提高系统的吞吐量和效率,而[2]是一旦有处理请求和要求处理的数据时,就立即应该处理该数据并将结果及时送会,例如[4]________________________等。

供选择的答案:[1][2][3] A、单用户系统B、批处理系统C、分时系统D、微机操作系统E、实时系统[4] A、计算机激光照排系统B、办公自动化系统C、计算机辅助设计系统D、航空售票系统2.操作系统是用户和计算机之间的接口,用户通过________________________、________________________与操作系统取得联系。

A、输入/输出设备B、命令接口C、中断服务程序D、系统调用3.常用的作业调度算法有____________________、____________________、____________________和____________________。

A、先来先服务法B、先进先出法C、最短作业优先法D、优先数法E、响应比高者优先法F、最近最少使用淘汰法4.文件的存储方法依赖于____________________和____________________。

A、文件的物理结构B、存放文件的存储设备的特性C、文件类型D、文件的逻辑结构5.设备管理的主要程序之一是设备分配程序,当进程请求在主存和外设之间传送信息时,设备分配程序分配设备的过程通常是____________________。

A、先分配设备,再分配控制器,最后分配通道B、先分配控制器,再分配设备,最后分配控制器C、先分配通道,再分配设备,最后分配控制器D、先分配通道,再分配控制器,最后分配设备6.进程执行时的间断性,决定了进程可能具有多种状态。

首次适应算法和最佳适应算法【讲解】

首次适应算法和最佳适应算法【讲解】

首次适应算法和最佳适应算法是动态存储分配解决方案研究的内容,所以本文对这两种算法的讨论是通过研究动态存储管理来进行的。

一、存储管理的基本问题:存储管理讨论的基本问题是:1)、系统如何应用户的“请求”执行内存分配动作?2)、系统如何对用户不再使用后“释放”的内存执行回收动作,以保证为新的“用户请求”提供内存分配?内存的分配可以以静态方式进行,内存空间被分割为固定大小的若干内存块,用户的请求到达只要找到一块空闲的内存块予以分配即可,很显然静态存储分配的好处主要是实现比较方便,效率高,程序执行中系统需要做的事情比较简单。

然而实际情况下提出“请求”的用户可能是进入系统的一个作业,也可能是程序执行过程中的一个动态变量。

“请求”需要获得的内存容量大小不一,这种做法造成了对程序大小的严格的限制,使某些问题不能够合理的解决,此外,也会造成内存空间的浪费。

动态存储管理就是确定如何满足一个个内存“请求”,如何更合理的使用有限的内存空间的一种内存分配解决方案,它以能够依据用户的请求依次进行内存空间的分配和回收,能够尽可能少的使用有限的空闲内存空间,最大限度的保证后续“请求”的可满足性为最终目的。

二、关于动态分配方案的分析:通常我们将已分配给用户是用的一段连续的内存空间称为“占用块”,将未分配给任何用户的一段连续的内存空间称为“可利用空间块”或者“空闲块”,我们在这里的描述将使用“占用块”和“空闲块”这两个概念。

整个内存区在没有任何用户进入和运行的情况下只有一个空闲块,即整个可供用户“请求”使用的用户内存区域。

随着不断的有用户请求进入系统,并依次获得系统为其分配的内存,使得整个内存区域逐渐被分割成两大部分:低地址区域包含若干占用块;高低址区域是空闲内存区域。

经过一段时间后,有的用户运行结束,它们所占用的内存区释放后转变为一个个空闲块,这就使整个内存区域呈现出占用块和空闲块交错相隔的状态。

而此时,如果再有新的用户“请求”到达,那么,系统如何为这个“请求”进行内存分配呢?在肯定动态存储管理的前提下,我们可以采取两种方案解决这个问题,一种解决方案是系统继续把高地址的空闲块分配给用户,而不理会低地址区域是否有结束执行的用户释放的内存块,直到剩余的高地址区域的空闲块不能满足新的用户“请求”,分配操作无法再进行下去时,才去回收结束执行的用户释放的内存块,并重新组织内存,进而完成内存分配。

操作系统 分区分配法 最佳适应算法

操作系统 分区分配法 最佳适应算法
t=A[k0][j];
A[k0][j]=A[i][j];
A[i][j]=t;
}
}
}
printf("\n----最佳适应算法按空闲区的容量从小到大排列后空闲区----\n");
printf("\t分区号\t\t大小\t\t起始地址\n");
for(i=0;i<m;i++)
for(j=0;j<3;j++)
t=A[k0][j];
A[k0][j]=A[i][j];
A[i][j]=t;
}
}
}
printf("\n----最坏适应算法按空闲区的容量从大到小排列后空闲区----\n");
printf("\t分区号\t\t大小\t\t起始地址\n");
for(i=0;i<m;i++)
for(j=0;j<3;j++)
scanf("%d",&A[i][j]);
/*按地址从小到大排列(直接选择排序) */
for(i=0;i<m-1;i++)
{ k0=i;
for(k=i+1;k<m;k++)
if(A[k][2]<A[k0][2])k0=k;
if(k0!=i)
{ for(j=0;j<3;j++)
{ int t;
t=A[k0][j];
#include<stdio.h>
void main()
{ int m,n,i,j,j0,k,k0,A[30][3],B[30];

首次适应算法最佳适应算法最坏适应算法

首次适应算法最佳适应算法最坏适应算法

首次适应算法最佳适应算法最坏适应算法首次适应算法(First Fit Algorithm)是一种常见的内存分配算法,用于管理计算机的物理内存。

它的核心思想是将内存按照从低地址到高地址的顺序进行划分,每次分配内存时从低地址开始,找到第一个足够大的空闲块来满足需求。

首次适应算法的实现相对简单,它只需要维护一个空闲内存块链表,其中存储了空闲块的起始地址和大小。

当需要分配一块内存时,首次适应算法会遍历链表,找到第一个大小足够的空闲块并将其划分为两部分:一部分用于分配,另一部分作为一个新的空闲块。

同样,当需要释放一块已分配的内存时,首次适应算法会查找内存中是否存在相邻的空闲块,若有则合并。

首次适应算法的优点是简单、高效,分配内存的时间复杂度为O(n),其中n是空闲内存块的数量。

然而,首次适应算法也存在一些问题。

首先,它可能会导致内存碎片的产生。

当分配的内存大小比较小且频繁时,会导致大量的小块空闲内存,造成内存碎片化。

其次,由于首次适应算法是按顺序空闲块来找到最适合的块,因此可能会导致较大的块被拆分成多个小块,从而降低内存的利用率。

最佳适应算法(Best Fit Algorithm)是一种改进的内存分配算法,旨在解决首次适应算法中存在的问题。

最佳适应算法的核心思想是在每次分配内存时,选择最小的能满足需求的空闲块。

最佳适应算法的实现与首次适应算法类似,但不同之处在于它需要在遍历空闲块链表时记录下最小的满足条件的块。

当找到最小的空闲块后,将其划分为分配块和新的空闲块。

最佳适应算法的优点是减少了内存碎片的产生。

通过选择最小的能满足需求的空闲块,可以更好地利用内存。

然而,最佳适应算法的缺点是实现复杂度较高。

由于需要在空闲块链表中查找最小的块,分配内存的时间复杂度为O(n),其中n是空闲内存块的数量。

最坏适应算法(Worst Fit Algorithm)是一种与最佳适应算法相反的内存分配算法。

它的核心思想是在每次分配内存时,选择最大的能满足需求的空闲块。

广工 操作系统课程设计 最佳适应算法、最坏适应算法、循环首次适应算法

广工 操作系统课程设计 最佳适应算法、最坏适应算法、循环首次适应算法

动态分区分配算法仿真,循环首次适应算法、最佳适应算法、最坏适应算法#include<iostream>#include<iomanip>//在输入输出流中用到控制符#include<windows.h>//用到了SetConsoleTextAttribute函数#define minsize 2//事先规定的不再切割的剩余分区大小为2using namespace std;struct Node{int name;int start;int size;int state;Node *pre;Node *next;};typedef struct Dlinklist{Node *head;}Dlist;//===================Dlist pro,fre;int memory,name,size,fit;Node *temp=NULL;//temp是NestFit算法中的起始查寻指针//===================void initDlist(Dlist &L)//创建带有头结点的双向链表{L.head=new Node;L.head->next=L.head->pre=NULL;}void MemoryInit()//初始化两个链表{initDlist(pro); //process链表initDlist(fre); //free block链表Node *p=new Node;p->name=0;p->start=0;p->state=0;p->size=memory;p->next=NULL;//这里曾错写成p->pre..............p->pre=fre.head;//这里曾漏写fre.head->next=p;}int getLength(Dlist &L)//返回链表的长度,即元素的个数int m=0;Node *p=L.head->next;while(p!=NULL){m++;p=p->next;}return m;}void arrangeSmaller(Dlist &L)//冒泡排序,链表按size进行排序,从小到大{int length=getLength(L);for(int i=0; i<length-1; i++)//当链表中的元素个数>=2的时候才排序{Node *p=L.head->next;Node *q=p->next;inta,b,c,d;//===================================================================== =====for(int j=0; j<length-1-i; j++){if(p->size>q->size) //交换位置,如果前面的大于后面的,使小的上浮,如果两个相等,则还是原来在前的保持在前{a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}void arrangeBigger(Dlist &L)//链表按size进行排序,从大到小{int length=getLength(L);for(int i=0; i<length-1; i++){Node *p=L.head->next;Node *q=p->next;int a,b,c,d;for(int j=0; j<length-1-i; j++){if(p->size<q->size){a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}}void arrangeStart(Dlist &L)//链表按start递增排序{int length=getLength(L);for(int i=0; i<length-1; i++){Node *p=L.head->next;Node *q=p->next;int a,b,c,d;for(int j=0; j<length-1-i; j++){if(p->start>q->start){a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}}void DlistInsert(Dlist &L,Node e) //在头结点之后插入元素,即L.head->next指向e {Node *p=new Node;p->name=;p->size=e.size;p->start=e.start;p->state=e.state;if(L.head->next!=NULL)//这是个值得注意的地方,L.head->next==NULL,则没有指针L.head->next->pre,如果这里不加判断的话,会出错L.head->next->pre=p;p->next=L.head->next;p->pre=L.head;L.head->next=p;//双向链表,插入一个新的元素,如果元素不是插入在链尾,则一共要修改四次指针}void DlistDelete(Node *p,Node &e)//传递指针p,删除指针p指向的链表元素,用Node 型变量e记录该元素的相关数据{=p->name;e.start=p->start;e.size=p->size;e.state=p->state;p->pre->next=p->next;//这里曾写成=p->pre....if(p->next!=NULL)p->next->pre=p->pre;//这里曾写成p->next->pre=p,留意delete(p); //删除一个元素修改一次或两次指针}//=======================void Green(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_GREEN);}void Red(){ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_RED);}void White(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FORE GROUND_GREEN|FOREGROUND_BLUE);}void Yellow(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_RED|FOREGROUND_GREEN);}//=======================void BestOrWorst(){arrangeStart(fre);//先按地址递增排序if(fit==1)arrangeSmaller(fre);//再按size递增排序,当两个空闲区的size一样时,由于先按地址递增排序了,所以还是地址低的在前。

循环首次适应算法

循环首次适应算法

循环首次适应算法在FFC算法中,内存被划分为一系列大小相等的分区,每个分区可以容纳一个作业。

当作业需要分配内存时,FFC算法会按照分区的顺序查找合适的空闲分区来分配内存。

如果找到了一个空闲分区,且该分区的大小大于或等于所需内存大小,就将作业分配到该分区中。

如果找不到合适大小的分区,则进入下一次循环,继续从头开始查找。

以下是FFC算法的主要步骤:1.初始化内存空间:将可用的内存空间划分为大小相等的分区,并将每个分区标记为“空闲”,同时维护一个分区链表,记录所有空闲分区的起始地址。

2.作业请求内存:当一个作业请求分配内存时,算法会从分区链表的头部开始遍历,寻找第一个满足大小需求的空闲分区。

3.分配内存:如果找到了合适的空闲分区,则将该分区标记为“已分配”,并将作业放入该分区。

4.更新分区链表:如果被分配的分区大小超过了作业的大小,将该分区分割成两个部分,并将剩余的空闲部分插入分区链表中。

如果被分配的分区大小恰好等于作业的大小,则将该分区从链表中移除。

5.释放内存:当一个作业释放内存时,将该分区标记为“空闲”。

然后,检查该分区的相邻分区是否也是空闲分区,如果是,则将相邻分区合并成一个更大的空闲分区,并更新分区链表。

6.回到步骤2,继续处理下一个作业请求。

循环首次适应算法的优点是容易实现和理解,同时由于循环链表的使用,可以减少对内存空间的遍历次数,提高分配效率。

然而,该算法也存在一些缺点。

例如,由于分区大小相等,可能会出现所需内存大小较小,但仍无法得到满足的情况。

此外,由于分区合并的操作,可能会产生大量的内部碎片。

循环首次适应算法是动态内存分配中常用的一种算法,它在现代操作系统和编程语言中得到广泛应用。

通过合理配置内存空间,可以提高内存的利用率,并增强系统的性能和稳定性。

通过对FFC算法的理解和优化,可以更好地管理和使用内存资源。

首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法

首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法

首次适应算法、循环首次适应算法、最佳适应算法和最坏适应算法是关于操作系统内存管理中内存分配策略的四种典型算法。

以下是对它们的简要解释:1. 首次适应算法(First-fit):在内存分配时,首次适应算法从内存区域的起始部分开始搜索,找到第一个能满足请求大小的空闲内存块,并将其分配给请求者。

首次适应算法的优点是分配速度较快,但可能导致内存空间碎片化。

2. 循环首次适应算法(Next-fit):循环首次适应算法类似于首次适应算法,但它在内存分配时保留上一次搜索的位置。

下一次分配时,算法将从上次停止的位置开始搜索,直到找到合适的空闲内存块或返回到起始位置。

这种方法可以在整个内存空间中分散分配过程,进一步改善内存碎片化问题。

3. 最佳适应算法(Best-fit):最佳适应算法在分配内存时,会查找所有可用的空闲内存块,并分配能够最紧密地满足请求大小的内存块。

该策略试图使分配后的剩余空间尽量小,以减少内存浪费。

然而,最佳适应算法通常需要更多的搜索时间,并可能导致过多的小内存碎片。

4. 最坏适应算法(Worst-fit):最坏适应算法与最佳适应算法相反,它在分配内存时选择最大的可用内存块。

这种策略试图保持较大的连续空闲内存块,以便满足大型请求。

然而,最坏适应算法可能导致大量空间浪费,并需要较长的搜索时间。

这些内存分配算法都有各自的优缺点。

在实际的操作系统实现中,可能会根据需求和上下文使用多种算法的组合来优化内存管理。

操作系统实验四 主存空间的分配与回收-首次适应算法和循环首次适应算法

操作系统实验四 主存空间的分配与回收-首次适应算法和循环首次适应算法

实验报告【实验名称】首次适应算法和循环首次适应算法【实验目的】理解在连续分区动态的存储管理方式下,如何实现主存空间的分配与回收。

【实验原理】首次适应(first fit,FF)算法FF算法要求空闲分区链以地址递增的次序链接。

在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区即可。

然后再按照作业的大小,从该分区中划出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。

若从链首直至链尾都不能找到一个能满足要求的分区,则表明系统中已经没有足够大的内存分配给该进程,内存分配失败,返回。

循环首次适应(next fit,NF)算法为避免低址部分留下许多很小的空闲分区,以及减少查找可用空闲分区的开销,循环首次适应算法在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块玉请求大小相等的内存空间分配给作业。

【实验内容】实现主存空间的分配与回收:1.采用可变式分区管理,使用首次适应算法实现主存空间的分配与回收;2.采用可变式分区管理,使用循环首次适应算法实现主存空间的分配与回收。

数据结构和符号说明:typedef struct PCB//进程控制块{char ProgressName[10]; //进程名称int Startaddress; //进程开始地址int ProgressSize; //进程大小int ProgressState = 0; //进程状态};typedef struct FREE //空闲区结构体{int Free_num; //空闲区名称int Startaddress; //空闲区开始地址int Endaddress; //空闲区结束地址int Free_Space; //空闲区大小};算法流程图:首次适应算法循环首次适应算法程序代码及截图:主界面:首次适应算法,初始空闲区:插入进程:插入3个进程:空闲区信息:删除进程2:删除后空闲区状况:再插入一个进程,可以看到其其初始地址为100:循环首次适应算法,插入3个进程删除进程2后:再插入进程A,发现其从上次找到的空闲分区的下一个空闲分区开始查找,其初始地址为750而不是200:。

首次适应算法、最佳适应算法和最差适应算法

首次适应算法、最佳适应算法和最差适应算法

⾸次适应算法、最佳适应算法和最差适应算法关于⾸次适应算法、最佳适应算法和最差适应算法,先看⼀下百度百科的解释,已经说出了三者的最⼤区别。

⾸次适应算法(first-fit):从空闲分区表的第⼀个表⽬起查找该表,把最先能够满⾜要求的空闲区分配给作业,这种⽅法的⽬的在于减少查找时间。

最佳适应算法(best-fit):从全部空闲区中找出能满⾜作业要求的,且⼤⼩最⼩的空闲分区,这种⽅法能使碎⽚尽量⼩。

最差适应算法(worst-fit):它从全部空闲区中找出能满⾜作业要求的、且⼤⼩最⼤的空闲分区,从⽽使链表中的节点⼤⼩趋于均匀。

下⾯看⼀个实例:Given five memory partitions of 100 KB, 500 KB, 200 KB, 300 KB, and 600 KB (in order), how would each of the first-fit, best-fit, and worst-fit algorithms place processes of 212 KB, 417 KB, 112 KB, and 426 KB (in order)? Which algorithm makes the most efficient use of memory?⾸次适应算法:为212k分配空间:依次找寻,找到第⼀个⼤于212k的空闲区;找到第⼆个空闲区500k>212k,分配给212k,剩余288k空闲区;为417k分配空间:依次找寻,找到第⼀个⼤于417k的空闲区;找到第五个空闲区600k>417k,分配给417k,剩余183k空闲区为112k分配空间:依次找寻,找到第⼀个⼤于112k的空闲区;找到第⼆个空闲区288k>112k,分配给112k,剩余176k空闲区为426k分配空间:依次找寻,找到第⼀个⼤于426k的空闲区;未找到,此作业将等待释放空间最佳适应算法:为212k分配空间:找到第⼀个跟212k⼤⼩最接近的空闲区找到第四个空闲区300>212k,剩余88k空闲区为417k分配空间:找到第⼀个跟417k⼤⼩最接近的空闲区找到第⼆个空闲区500>417,剩余83k空闲区为112k分配空间:找到第⼀个跟112k⼤⼩最接近的空闲区找到第三个空闲区200>112k,剩余88k空闲区为426k分配空间:找到第⼀个跟426⼤⼩最接近的空闲区找到第五个空闲区600k>426,剩余74k空闲区最坏适应算法:为212k分配空间:找到第⼀个⼤⼩最⼤的空闲区找到第五个空闲区600>212k,剩余388k空闲区为417k分配空间:找到第⼀个⼤⼩最⼤的空闲区找到第⼆个空闲区500>417,剩余83k空闲区为112k分配空间:找到第⼀个⼤⼩最⼤的空闲区找到第三个空闲区388>112k,剩余276k空闲区为426k分配空间:找到第⼀个⼤⼩最⼤的空闲区达到⼤⼩最⼤的空闲区300k<426k,所以不分配ps:好久没碰操作系统了,今天看到这三个算法的第⼀反应居然有点懵,还是好记性不如烂笔头啊,本⽂中的定义来⾃百度百科,实例题⽬来⾃⽼师布置的作业,答案分析为笔者按⾃⼰的理解写的,若有不对,欢迎指出~~。

c模拟内存分配算法(首次适应算法,最佳适应算法,最坏适应算法)

c模拟内存分配算法(首次适应算法,最佳适应算法,最坏适应算法)

c模拟内存分配算法(⾸次适应算法,最佳适应算法,最坏适应算法)#include<bits/stdc++.h>using namespace std;/*定义内存的⼤⼩为100*/#define MEMSIZE 100/*如果⼩于此值,将不再分割内存*/#define MINSIZE 2/*内存分区空间表结构*/typedef struct _MemoryInfomation{/*起始地址*/int start;/*⼤⼩*/int Size;/*状态 F:空闲(Free) U:占⽤(Used) E 结束(End)*/char status;} MEMINFO;/*内存空间信息表*/MEMINFO MemList[MEMSIZE];/*显⽰内存状态*/void Display(){int i,used=0;//记录可以使⽤的总空间量printf("\n---------------------------------------------------\n");printf("%5s%15s%15s%15s","Number","start","size","status");printf("\n---------------------------------------------------\n");for(i=0; i<MEMSIZE&&MemList[i].status!='e'; i++){if(MemList[i].status=='u'){used+=MemList[i].Size;}printf("%5d%15d%15d%15s\n",i,MemList[i].start,MemList[i].Size,MemList[i].status=='u'?"USED":"FREE");}printf("\n----------------------------------------------\n");printf("Totalsize:%-10d Used:%-10d Free:%-10d\n",MEMSIZE,used,MEMSIZE-used);}/*初始化所有变量*/void InitMemList(){int i;MEMINFO temp= {0,0,'e'};//初始化空间信息表for(i=0; i<MEMSIZE; i++){MemList[i]=temp;}//起始地址为0MemList[0].start=0;//空间初始为最⼤MemList[0].Size=MEMSIZE;//状态为空闲MemList[0].status='f';}/*最先适应算法*//*算法原理分析:将空闲的内存区按其在储存空间中的起始地址递增的顺序排列,为作业分配储存空间时,从空闲区链的始端开始查找,选择第⼀个满⾜要求的空闲区,⽽不管它究竟有多⼤优点:1.在释放内存分区的时候,如果有相邻的空⽩区就进⾏合并,使其成为⼀个较⼤的空⽩区2.此算法的实质是尽可能的利⽤储存器的低地址部分,在⾼地址部分则保留多的或较⼤的空⽩区,以后如果需要较⼤的空⽩区,就容易满⾜缺点:1.在低地址部分很快集中了许多⾮常⼩的空⽩区,因⽽在空⽩区分配时,搜索次数增加,影响⼯作效率。

操作系统分区分配法最佳适应算法

操作系统分区分配法最佳适应算法

操作系统分区分配法最佳适应算法
最佳适应算法是一种用于操作系统中进行内存分区分配的算法。

该算
法的目标是在内存中找到一个最适合所需内存大小的分区。

最佳适应算法的工作过程如下:
1.初始化内存分区列表,包含所有内存分区的大小和状态(可用或占用)。

2.当一个作业请求分配内存时,算法遍历内存分区列表,找到一个最
小的足够容纳该作业的可用分区。

3.如果找到合适的分区,则将该分区分割成两个部分:一部分为作业
所需大小,另一部分为剩余的可用空间。

4.如果找不到合适的分区,则作业无法分配内存。

优点:
1.最佳适应算法保证所分配的分区是最适合作业大小的,可以最大程
度地利用内存空间。

2.由于内存分区列表已经按照大小排序,算法的查找时间复杂度较低。

缺点:
1.最佳适应算法可能导致内存碎片,即分散在多个分区中的未使用的
小块内存空间。

这些碎片会影响内存利用率。

2.每次作业请求分配内存时,需要遍历整个分区列表,时间复杂度较高。

3.需要维护并更新内存分区列表,对内存管理的开销较大。

在实际应用中,最佳适应算法往往与其他算法结合使用,以平衡内存分配的效率和碎片化问题。

例如,可以使用首次适应算法或循环首次适应算法进行内存分配,以减少内存碎片。

然后,当有大作业请求内存时,再使用最佳适应算法进行内存分配,以最大程度地利用内存空间。

总之,最佳适应算法是一种常用的内存分区分配算法,通过找到最适合作业大小的分区来分配内存。

尽管算法可能导致内存碎片和时间复杂度较高,但在实际应用中可以与其他算法结合使用,以平衡内存利用率和分配效率。

操作系统实验-首次适应算法与循环首次适应算法

操作系统实验-首次适应算法与循环首次适应算法

操作系统实验-首次适应算法与循环首次适应算法首次适应算法循环首次适应算法程序代码及截图:#include<stdio.h>#include<string.h>#define N 1024bool ROM[N];//设置内存块int p=0;//循环首次使用需要标记当前的空闲区块typedef struct Pcb//作业数据结构{char name[10];int start;int size;int state=0;} pcb;int free_rom_counter=0;pcb num[20]; //作业队列typedef struct Free_rom //空闲区结构体{int num;int start;int end;int space;} Free_room;Free_rom free_rom[100];//设置空闲区数组为100个void find_free_rom() //寻找空闲区{free_rom_counter=0;int i,j,p;for(i=0; i<N; i++)if(ROM[i]==0){p=i;for(j=i; j<N; j++){if(ROM[j]==0){i=j;continue;}if(ROM[j]==1)//找到空闲区{free_rom_counter++;free_rom[ free_rom_counter].num= free_rom_counter;free_rom[ free_rom_counter].start=p;free_rom[ free_rom_counter].end=j-1;free_rom[ free_rom_counter].space=j-p;i=j+1;break;}}if(j==N&&ROM[j-1]==0)//对最后一个内存进行特殊操作{free_rom_counter++;free_rom[ free_rom_counter].num= free_rom_counter;//对空闲区进行处理free_rom[ free_rom_counter].start=p;free_rom[ free_rom_counter].end=j-1;free_rom[ free_rom_counter].space=j-p;}}}void init()//初始化{for(int i=0; i<N; i++)ROM[i]=0;}void show(){printf("空闲区名\t开始地址\t\t大小\t\t结束地址\t\t\n");for (int i=1; i<= free_rom_counter; i++)printf("%d\t\t%d\t\t\t%d\t\t%d\t\t\n",free_rom[ i].num,free_rom[ i]. start, free_rom[ i].space,free_rom[ i].end);}void insert_pcb1(pcb &a)//首次适应算法来实现作业调度{int i,j,k;for(i=0; i<N; i++)if(ROM[i]==0){for(j=i; j<=(i+a.size)&&j<N; j++)//查询第一个空闲区,并判断是否适合插入作业if(ROM[j]==1){i=j+1;break;}if(j==i+a.size+1){a.start=i;//设置作业的开始内存a.state=1;//标记作业在内存中for(k=i; k<i+a.size&&j<N; k++)ROM[k]=1;printf("插入成功,进程%s 的初始地址为%d,结束地址为%d\n",,a.start,a.start+a.size-1);return;}}if(i==N)//未查询到合适的区域printf("插入失败,无可用空间\n");}void insert_pcb2(pcb &a)//循环首次适应算法来实现作业调度{int i,j,k;for(i=p; i<N; i++)//从所标记的当前区域开始查询,查询到末内存 {if(ROM[i]==0){for(j=i; j<=(i+a.size)&&j<N; j++)if(ROM[j]==1){i=j+1;break;}if(j==i+a.size+1)//找到合适的空闲区{a.start=i;a.state=1;for(k=i; k<i+a.size&&j<N; k++)ROM[k]=1;printf("插入成功,进程%s 的初始地址为%d,结束地址为%d\n",,a.start,a.start+a.size-1);p=i+a.size;return;}}}for(i=0; i<p; i++)//当未找到时,从第一个空闲区开始查询,结束条件为小于所标记的Pif(ROM[i]==0){for(j=i; j<=(i+a.size)&&j<p; j++)if(ROM[j]==1){i=j+1;break;}if(j==i+a.size+1)//成功找到结束,并标记当前P为现在的作业的尾部{a.start=i;a.state=1;for(k=i; k<i+a.size&&j<p; k++)ROM[k]=1;printf("插入成功,进程%s 的初始地址为%d\n",,a.start);p=i+a.size;break;}}if(i==p)//查询两部分都未找到合适的区域,输出插入失败语句printf("插入失败,无可用空间\n");}void Delete(pcb &a)//删除作业,修改内存信息和初始化该作业信息{int i;for(i=a.start; i<a.start+a.size; i++)ROM[i]=0;a.state=0;//状态标记为未使用printf("删除成功\n");}int main(){init();int count=0;int choose1,choose;char name[10];pcb a;printf("1、首次适应算法\n");printf("2、循环首次适应算法\n");scanf("%d",&choose1);do{printf("\n\n1、插入进程\n");printf("2、删除进程\n");printf("3、显示进程的信息\n");printf("4、显示空闲区\n");scanf("%d",&choose);if(choose==1){printf("输入进程名\n");scanf("%s",&);printf("输入进程大小\n");scanf("%d",&a.size);if(choose1==1)insert_pcb1(a);else insert_pcb2(a);num[count++]=a;}else if(choose==2){printf("输入删除进程的名字\n");scanf("%s",&name);for(int i=0; i<count; i++)if( !strcmp(num[i].name,name))Delete(num[i]);}else if(choose==3){printf("进程名\t\t开始地址\t\t大小\t\t结束地址\t\t\n");//输出内存信息for(int i=0; i<count-1; i++)for(int j=i; j<count-1; j++)if(num[j].start>num[j+1].start){a=num[j];num[j]=num[j+1];num[j+1]=a;}for(int i=0; i<count; i++)if(num[i].state!=0)printf("%s\t\t%d\t\t\t%d\t\t%d\t\t\n",num[i].name,num[i].start,num[i ].size,num[i].size+num[i].start-1);}else if(choose==4){find_free_rom();show();}else break;}while(1);return 0;}首次适应算法:本实验共采用1024个内存进行模拟,首先对内存初始化,得到一个大的空闲区:相继插入3个进程:分别插入进程A B C,大小分别为100,200,300 此时查询进程信息和查询空闲区信息有一块大小为424 起始地址为600的空闲区在进行插入D删除B此时有两块空闲区插入一个150大小的进程,他的起始地址应为100此时空闲区只有2块,一块大小为50,删除C 进程,构造一块大空闲区再插入一个进程为100大小,此时两块空闲区都满足,此时应从第一块插入再插入一个大于两块空闲区大小的进程,此时无可用空间首次适应算法完成。

【操作系统】分区分配算法(首次适应算法、最佳适应算法)(C语言实现)

【操作系统】分区分配算法(首次适应算法、最佳适应算法)(C语言实现)

【操作系统】分区分配算法(⾸次适应算法、最佳适应算法)(C语⾔实现)【操作系统】分区分配算法(⾸次适应算法、最佳适应算法)(C语⾔实现)(编码⽔平较菜,写博客也只是为了个⼈知识的总结和督促⾃⼰学习,如果有错误,希望可以指出)今天测试,发现⼀点问题:1.最佳插⼊算法:对于插⼊的时候忘记修改temp.next.front的指向2.回收头节点的时候现在多了⼀种判断。

判断头节点的下⼀个是否为空。

对如果不为空⽽且后⾯的空闲的话,做出了处理。

原来则没有这⼀情况。

1.动态分区分配算法:为了实现动态分区分配,通常将系统中的空闲分区链接成⼀个链。

所谓顺序查找是指依次搜索空闲分区链上的空闲分区,去寻找⼀个⼤⼩能满⾜要求的分区。

--------计算机操作系统(第四版)2.动态分区算法主要包括四种:(1).⾸次适应算法(first fit,FF):要求,空闲分区链以地址递增的顺序链接。

每次从链⾸开始,直到找到第⼀个能满⾜要求的空闲分区为⽌。

简单来说,就是,每次都从第⼀个开始顺序查找,找到⼀块区域可以满⾜要求的。

优点:优先利⽤内存中低址部分的空闲分区,从⽽保留了⾼址部分的⼤空闲区,这为以后到达的⼤作业分配⼤的内存空间创造了条件。

缺点:低址部分不断被划分,会留下许多难以利⽤的,很⼩的空闲分区,称为碎⽚。

⽽每次查找⼜都是从低址部分开始的,这⽆疑⼜会增加查找可⽤空闲分区时的开销。

(2).循环⾸次适应算法(next fit,NF):与FF算法区别就是,不是每次都从⾸次开始,⽽是从上次找到的空闲分区的下⼀个空闲分区开始。

(第⼀次查找的话也是从⾸页开始)。

特点:能使内存中的空闲区分布得较均匀。

(3).最佳适应算法(best,BF):将所有空闲分区按照空闲分区容量⼤⼩从⼩到⼤的顺序连接起来,形成⼀个空闲分区链。

即,每次都是找空间容量不但可以满⾜要求的空闲区,⽽且该空闲分区的容量还要最接近要求的容量⼤⼩。

优点:每次分配给⽂件的都是最合适该⽂件⼤⼩的分区。

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

动态分区分配算法仿真,循环首次适应算法、最佳适应算法、最坏适应算法#include<iostream>#include<iomanip>//在输入输出流中用到控制符#include<windows.h>//用到了SetConsoleTextAttribute函数#define minsize 2//事先规定的不再切割的剩余分区大小为2using namespace std;struct Node{int name;int start;int size;int state;Node *pre;Node *next;};typedef struct Dlinklist{Node *head;}Dlist;//===================Dlist pro,fre;int memory,name,size,fit;Node *temp=NULL;//temp是NestFit算法中的起始查寻指针//===================void initDlist(Dlist &L)//创建带有头结点的双向链表{L.head=new Node;L.head->next=L.head->pre=NULL;}void MemoryInit()//初始化两个链表{initDlist(pro); //process链表initDlist(fre); //free block链表Node *p=new Node;p->name=0;p->start=0;p->state=0;p->size=memory;p->next=NULL;//这里曾错写成p->pre..............p->pre=fre.head;//这里曾漏写fre.head->next=p;}int getLength(Dlist &L)//返回链表的长度,即元素的个数int m=0;Node *p=L.head->next;while(p!=NULL){m++;p=p->next;}return m;}void arrangeSmaller(Dlist &L)//冒泡排序,链表按size进行排序,从小到大{int length=getLength(L);for(int i=0; i<length-1; i++)//当链表中的元素个数>=2的时候才排序{Node *p=L.head->next;Node *q=p->next;inta,b,c,d;//===================================================================== =====for(int j=0; j<length-1-i; j++){if(p->size>q->size) //交换位置,如果前面的大于后面的,使小的上浮,如果两个相等,则还是原来在前的保持在前{a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}void arrangeBigger(Dlist &L)//链表按size进行排序,从大到小{int length=getLength(L);for(int i=0; i<length-1; i++){Node *p=L.head->next;Node *q=p->next;int a,b,c,d;for(int j=0; j<length-1-i; j++){if(p->size<q->size){a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}}void arrangeStart(Dlist &L)//链表按start递增排序{int length=getLength(L);for(int i=0; i<length-1; i++){Node *p=L.head->next;Node *q=p->next;int a,b,c,d;for(int j=0; j<length-1-i; j++){if(p->start>q->start){a=p->size;p->size=q->size;q->size=a;b=p->name;p->name=q->name;q->name=b;c=p->start;p->start=q->start;q->start=c;d=p->state;//============================================================== ============p->state=q->state;q->state=d;}p=p->next;q=p->next;}}}void DlistInsert(Dlist &L,Node e) //在头结点之后插入元素,即L.head->next指向e {Node *p=new Node;p->name=;p->size=e.size;p->start=e.start;p->state=e.state;if(L.head->next!=NULL)//这是个值得注意的地方,L.head->next==NULL,则没有指针L.head->next->pre,如果这里不加判断的话,会出错L.head->next->pre=p;p->next=L.head->next;p->pre=L.head;L.head->next=p;//双向链表,插入一个新的元素,如果元素不是插入在链尾,则一共要修改四次指针}void DlistDelete(Node *p,Node &e)//传递指针p,删除指针p指向的链表元素,用Node 型变量e记录该元素的相关数据{=p->name;e.start=p->start;e.size=p->size;e.state=p->state;p->pre->next=p->next;//这里曾写成=p->pre....if(p->next!=NULL)p->next->pre=p->pre;//这里曾写成p->next->pre=p,留意delete(p); //删除一个元素修改一次或两次指针}//=======================void Green(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_GREEN);}void Red(){ SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_RED);}void White(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED|FORE GROUND_GREEN|FOREGROUND_BLUE);}void Yellow(){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSIT Y|FOREGROUND_RED|FOREGROUND_GREEN);}//=======================void BestOrWorst(){arrangeStart(fre);//先按地址递增排序if(fit==1)arrangeSmaller(fre);//再按size递增排序,当两个空闲区的size一样时,由于先按地址递增排序了,所以还是地址低的在前。

if(fit==2)arrangeBigger(fre);Node e;int flag=0;Node *p=fre.head->next; /*p=fre.head->next,而这时fre是不可能为空的,因为在input()中加入了判断,如果输入了allocate的请求时,如果fre为空,则不会执行BestOrWorst()故不用讨论fre是否为空的情况。

也就是说,在进入BestOrWorst()的时候就已经确保了fre.head->next!=NULL, 同理,进入NextFit()的时候也保证了fre不为空*/while(p!=NULL){ //遍历fre链表,当找到合适的空间之后就break if(p->size>=size){flag=1;break;//一定要break不然遇到两个size相同的空闲区就会出现两个都分配出去的状况}p=p->next;}if(flag==0)//在fre链表不空的前提下,如果flag==0则说明没有找到合适的空闲区间,所以分配失败{Red();cout<<" No fitting block,failed to allocate memory!!"<<endl;}else{if(p->size-size<=minsize){p->state=2;//============================================================== ============DlistDelete(p,e);=name; //这里注意了,不是=p->name因为fre链表中所有的name全部被我置为0,所以当把空闲区间分配给process的时候一定要记得把名字加进去//其实state对操作什么的都完全没有影响,可改可不改,但为了规范,还是改一下吧DlistInsert(pro,e);/*这里还有的一个问题是,例如,当输入的信息为name=1,size=48KB,而将要分配给它的空闲区间p->size=50,这样,当在表格中输出的时候该process的信息是name=1,size=50KB,也就是说它的实际大小向p->size看齐了,但如果这里让e.size=size的话,输出来的信息确实跟原来输入的时候对应了,但是当kill这个进程的时候,回收的空间并不等于之前分配出去时的空间,会导致memory发生变化 */}else{e.state=2;//=============================================================== ============name; //同理e.start=p->start;// e.state=1;e.size=size;DlistInsert(pro,e);p->start=p->start+size;//只要修改一下原来空闲区间的start和size即可p->size=p->size-size;p->state=2;//================================================== }Yellow();cout<<" Memory allocated"<<endl;}}void NextFit(){arrangeStart(fre);Node e;Node *p=NULL;//在这里不用讨论fre是否为空,因为只有fre不为空才会执行NextFit(),详情请看input()int flag=0;int length=getLength(fre);if(temp==NULL) //if(length==1 || temp==NULL)当上一次进行分配的空间为链尾元素,则temp会指向NULL,这里加了个length==1,是因为p=fre.head->next; //第一次执行NextFit()的时候,Node *temp=new Node,但是后来改进了,直接在声明temp的时候就让temp=NULL,这样一来,第一次执行NextFit()的时候也能通过elsep=temp;while(length>0){if(p->size>=size){flag=1;break;}length--;if(p->next==NULL)//这里也是值得注意的地方p=fre.head->next;elsep=p->next;}if(flag==0)//没有找到合适的空闲区间来进行分配{Red();cout<<" No fitting block,failed to allocate memory!!"<<endl;}else{if(p->size-size<=minsize){//因为reclaim操作并不会减少fre中的元素,只有可能增加而已,所以只要在这个函数体内记录好temp就行。

相关文档
最新文档