课程设计报告课程设计题目:循环首次适应的动态分区分配算法模拟专业:计算机科学与技术班级:10204102姓名:谱学号: 10204102指导教师:高小辉2013年1月11 日目录一.循环首次适应算法 (3)1. 概述 (3)2.需求分析 (3)二.实验指导 (4)1.基本思想 (4)2.数据结构 (4)三.运行环境 (6)四.流程图 (6)五.循环首次适应算法代码 (5)六.调试结果 (11)七、总结 (14)八.参考文献 (14)一.循环首次适应算法1.概述:该算法是由首次适应算法演变而成的。
在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块的请求大小相等的内存空间分配给作业。
为实现该算法,应设置一起始查找指针,用于指示下一次起始查询的空闲分区,并采用循环查找方式,即如果最后一个(链尾)空闲分区的大小仍不能满足要求,则返回到第一个空闲分区,比较大小是否满足,找到后,应调整起始查询指针。
2. 需求分析了解动态分区分配中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解。
采用首次适应算法的动态分区分配过程alloc()和回收过程free()。
空闲分区通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲区低端的空间,即每次分配内存空间是总是从低址部分开始进行循环,找到第一个合适的空间,便按作业所需分配的大小分配给作业。
作业完成时,需要释放作业所占空间,此时要考虑到四种情况:(1)回收区与插入点的前一个空闲分区相邻接。
此时将二者合并,修改前一分区的大小。
(2)回收区与插入点的后一空闲分区相邻接,将二者合并,用回收区的首址作为新空闲区的首址。
(3)回收区同时与插入点的前后两个空闲分区相邻接,三者合并,使用前一空闲分区的表项和首址。
(4)回收区单独存在。
二、实验指导1.基本思想动态分区是指系统不预先划分固定分区,而是在装入程序的时候划分内存区域,使得为程序分配的分区大小恰好等于该程序的需求量,且分区的个数是动态的。
显然动态分区有较大的灵活性,较之固定分区能获得好的内存利用率。
2.数据结构动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。
另一种也是最常用的就是空闲链表,由于对分区的操作是动态的,所以很难估计数据结构所占用的空间,而且空闲区表会占用宝贵的系统空间,所以提出了空闲链表的概念。
其特点是用于管理分区的信息动态生成并和该分区在物理地址上相邻。
这样由于可以简单用两个空闲块之间的距离定位已分配空间,不仅节约了系统空间,而且不必维持已分配空间的信息。
本实验是要做一个模拟程序,来模拟动态分区算法的分配和回收过程,并不是真正的去分配和回收内存。
基本的模拟方法有两种:1、先从内存中申请一块存储区,对这块存储区进行模拟的分配和回收活动。
2、不申请存储区,自己定义一块虚拟的存储区,对这块存储区进行模拟的分配和回收活动,分配和回收仅仅是对数据结构的修改而已。
三.运行环境:1.操作系统 WINDOWS XP2.编译软件 Microsoft Visual C++3.电脑配置:主频3.0GHz 内存512MB四.流程图1.程序结构如图:2.首次适应算法的结构如图:五.循环首次适应算法代码#include <iostream>#include <stdlib.h>#include <stdio.h>using namespace std;struct memory{struct memory *former; //前向指针 int address;//地址int num;//作业号int size;//分配内存大小int state;//状态0表示空闲1表示已分配struct memory *next; //后向指针};typedef struct memory MEMORY;MEMORY *mem;const int size_min=10;//内存允许的最小空闲块的大小void init(); //初始化内存块void exec();//执行相应算法void F_F(int); //依次初始化每个作业,并根据相应算法对作业分配内存void alloc(MEMORY *,MEMORY *);//分配内存算法(包括两种不同算法)void free(MEMORY *,int);//首次适应算法回收内存void sort(MEMORY *);//对内存链进行排序void insert(MEMORY *,MEMORY *); //按空间大小将作业顺序插入到内存链void print(MEMORY *);//打印内存链void main(){ //主函数int i=0;while(1){ //选择算法cout<<("\n欢迎进入!");cout<<("\nPlease select a number(1,0)");cout<<("\n 循环首次适应算法");cout<<" 0--中止程序"<<endl;cin>>i;if(i==1){ //首次适应算法cout<<("\n以下为首次适应算法:\n");init();exec();}elseexit(1);}}void init(){ //初始化内存容量mem=new MEMORY;mem->size=640;mem->former=0;mem->next=0;}void exec(){//执行算法while(1){//选择申请或释放内存操作cout<<"**************************"<<endl;cout<<"申请内存请输入作业号(1-6)"<<endl;cout<<"释放内存请输入数字8"<<endl;cout<<"中止程序请输入数字0"<<endl;cout<<"**************************"<<endl;int k;cin>>k;//根据k值选择相应的操作if(k>=1&&k<=7) F_F(k);if(k==8){int m;cout<<"请输入要释放的作业号:";cin>>m; //选择相应的回收算法free(mem,m);}else if(k==0){//回滚到选择算法的步骤break;}}}void F_F(int i){ //依次初始化每个作业,并根据相应算法对作业分配内存int work[]={130,60,100,200,160,60,50};//作业序列,i从1开始(与作业号对应),因此从第一个开始存放作业值,第0个值为0,不是作业cout<<"请输入要作业所需的内存大小:";MEMORY *running;running=(MEMORY *)malloc(sizeof(MEMORY));if(running!=NULL){ running->former=NULL;running->address=0;running->num=i; //i从1开始循环running->size=work[i]; //指定作业大小running->state=0; //作业未分配running->next=NULL;//根据相应算法为作业分配内存,详见alloc函数alloc(mem,running); print(mem); cout<<endl;}elsecout<<"没有足够的内存空间"<<endl;}void print(MEMORY *ptr){ //打印显示内存情况MEMORY *temp;temp=ptr->next;cout<<"\n内存链的状态为:"<<endl;while(temp!=NULL){if(temp->state==0){cout<<"内存空闲 "<<"起始地址为:"<<temp->address<<" 空闲空间大小为:"<<temp->size<<"k";}else{cout<<"内存已分配 "<<"起始地址为:"<<temp->address<<" 分配空间大小为:"<<temp->size<<"k" <<" 运行的作业号:"<<temp->num;}cout<<endl;temp=temp->next;}}void free(MEMORY *ptr,int i){ //首次适应算法作业处理完后释放内存空间MEMORY *previous,*current;previous=ptr; current=previous->next;while(current!=NULL){ //循环直到找到需要释放的作业位置if(current->state==1&¤t->num==i){ break;}previous=current;current=current->next;}if(current==NULL){ cout<<"内存中没有任何作业!!!"<<endl; return; }else if(current->next==NULL){ //当前作业为内存中最后一个作业if(previous->state==0){ //与前一个相邻空闲区合并previous->size=previous->size+current->size;previous->next=NULL;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //将状态改为0,即为空闲区current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}else if((current->next)->next==NULL)//p6{ //当前作业为倒数第二个作业(此种情况还是要单列出来讨论的否则会出现错误)if(previous->state==0&&(current->next)->state==0) //p7 { //释放的地址空间前后均为空闲区previous->size=previous->size+current->size+(current->next)->size; previous->next=NULL; //与下边else(其他情况的不同之处)cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if(previous->state==0) //p5{ //释放的地址空间前面有空闲块则把它和前面的合并previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if((current->next)->state==0) //p8{ //释放的地址空间后面有空闲块则把它和后面的空闲块合并current->size=current->size+(current->next)->size;current->state=0;current->next=NULL; //与下边else(其他情况的不同之处)cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //释放的地址空间前后都没有空闲块时直接把它的状态改为0current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}else{ //其他情况下(当前作业在链表中间)if(previous->state==0&&(current->next)->state==0) //p7 { //所释放空间前后均为空闲区previous->size=previous->size+current->size+(current->next)->size; ((current->next)->next)->former=previous;previous->next=(current->next)->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if(previous->state==0) //p5{ //释放的地址空间前面有空闲块则把它和前面的合并previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if((current->next)->state==0) //p8{ //释放的地址空间后面有空闲块则把它和后面的空闲块合并current->size=current->size+(current->next)->size;current->state=0;((current->next)->next)->former=current;current->next=(current->next)->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //处理完的作业前后都没有空闲块时直接把它的状态改为0current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}}void alloc(MEMORY *ptr,MEMORY *assign){ //根据算法分配内存(is_optimist状态)if(ptr->next==NULL){ //内存没有作业运行if(ptr->size>=assign->size){ //内存空间大于作业所需空间,为内存分配空间ptr->size=ptr->size-assign->size;assign->state=1;ptr->next=assign;assign->former=ptr;cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}else{cout<<"没有足够的内存空间为作业"<<(assign->num)<<"分配"<<endl; delete assign;}}else{ //内存中如果已经分配了空间MEMORY *previous,*current;previous=ptr;//previous为链表中的第一个元素current=previous->next;while(current!=NULL){//当前区间不为空(最后一个区间的next为空),即没有循环到最后//如果当前内存空间大于作业所需空间并且内存没有被分配//则结束循环,当前current位置即为要插入的位置if(current->size>=assign->size&¤t->state==0){break;}previous=current; //previous后移current=current->next;}if(current==NULL){ //空闲链中没有为作业分配所需的空间,即释放的空闲区间小于要分配的作业空间//不够用,则在所有作业后边另外再申请空闲区,如作业4if(ptr->size>=assign->size){ //内存中还有足够没分配的空闲空间为此作业分配//此时ptr指向内存上未分配空闲空间的起始地址assign->address =640-(ptr->size);ptr->size=ptr->size-assign->size;assign->state=1;assign->former=previous;previous->next=assign;cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}else{cout<<"没有足够的内存空间为作业"<<(assign->num)<<"分配"<<endl;}}else{ //释放的空闲链中有可为此作业分配的空间if((current->size-assign->size)<=size_min){ //空闲链所具备的空间与作业所需空间大小差不多时//直接把整个空闲块的空间分配给作业否则从空闲块中current->num=assign->num; //划出与作业等同的空间current->state=1;delete assign;cout<<"作业 "<<(current->num)<<"申请"<<(current->size)<<" "<<"k 的内存间"<<endl;}else{ //从空闲块中划分一块与作业大小等同的空间current->size=current->size-assign->size;assign->state=1;assign->address=current->address+current->size;if(current->next==NULL){ //此要分配的空间是空闲链的最后一个元素assign->former=current;current->next=assign;}else{assign->next=current->next;(current->next)->former=assign;assign->former=current;current->next=assign;}cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}}}}六.调试结果1输入条件作业1申请130KB;作业2申请60KB;作业3申请100KB;作业2释放60KB;作业4申请200 KB;作业3释放100 KB;作业1释放130 KB;作业5申请140 KB;作业6申请60 KB;作业7申请50KB;作业6释放60 KB2运行结果:七.总结本次操作系统课程设计让我掌握了动态分区分配的实质:动态分区分配是根据进程的实际需要,动态地为之分配内存空间。