可变分区存储管理方式的内存分配回收

合集下载

在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。

在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。

..实验三、四存储管理一、实验目的帮助学生理解在不同的存储管理方式下应如何实现主存空间的分配和回收。

理解好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能够合理地分配和使用这些存储空间。

二、实验环境1、Java环境三、实验时数:4学时四、实验容与步骤1.在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。

2.在可变分区管理方式下采用最正确适应算法实现主存储器的分配和回收。

3.在可变分区管理方式下采用最坏适应算法实现主存储器的分配和回收。

要求:1。

分配时输入作业号以及申请量。

2.回收时输入作业号。

3.每次分配或回收之后按如下格式按照起始地址从小到大输出存分配情况。

五、实验报告实验题目。

1.在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。

1、2、程序中使用的数据构造及符合说明。

用Node 类模拟表示存的当前状态。

通过Node数组来开辟一组存,然后用Link类来进展存的连接3、程序流程图。

// Node.javaclass Node{//用Node来模拟存的当前状态int start;int size;boolean state;int jobNo;public Node(){}public Node(int start,int size,boolean state,int jobNo){this.start = start;this.size = size;this.state = state;this.jobNo = jobNo;}public void print(){//打印Node类if (this!=null){System.out.println("起始位置"+this.start+"大小"+this.size+"状态"+this.state+"工作号"+this.jobNo);}}};//Link.javaclass Link{ //用Link类来模拟连接各个存,并添加作业public void addJob(int size,int jobNo,Node a[]){for(int i=0;i<a.length;i++){if(a[i]!=null){ //当前存有容时if(size<a[i].size&&a[i].state==false){ //判断是否符合条件a[i].size=a[i].size-size; //当前存分配大小给作业if(a[i+1]==null){ //当下一块存还没有使用时a[i+1]=new Node(size+a[i].start,size,true,jobNo);//使用该存}else{ //当下一块存已被使用,那么继续寻找一块还没被使用的存for(int j=i+1;j<a.length-1;j++){if(a[j]==null){a[j]=new Node(size+a[j-1].start,size,true,jobNo);break; //当找到未被使用的存及填入容后跳出循环}}}}a[i].print();//打印输出当前Link中各个存块的使用情况}}}public void delete(Node a[],int jobNo){//删除某一个进程,当该进程被删除后,进程所在存的状态变为falsefor(int i=0;i<a.length;i++){if(a[i]!=null){if(a[i].jobNo==jobNo){//a[i].size=0;a[i].state=false;a[i].jobNo=0;}if(a[i]!=null){a[i].print();}}}}public void back(Node a[]){ //进展状态为false的存的回收删除存状态为false 的存节点。

计算机操作系统内存管理系统可变分区存储管理方式的内存分配回收

计算机操作系统内存管理系统可变分区存储管理方式的内存分配回收

课程设计2可变分区存储管理方式的内存分配回收一、课程设计目的深入了解采用可变分区存储管理方式的内存分配回收的实现;二、预备知识存储管理中可变分区的管理方式;三、小组成员四、课程设计内容编写程序完成可变分区存储管理方式的内存分配回收;具体包括:确定内存空间分配表;采用最优适应算法完成内存空间的分配和回收;编写主函数对所做工作进行测试;五、设计思路:整体思路:可变分区管理方式将内存除操作系统占用区域外的空间看做一个大的空闲区;当作业要求装入内存时,根据作业需要内存空间的大小查询内存中的各个空闲区,当从内存空间中找到一个大于或等于该作业大小的内存空闲区时,选择其中一个空闲区,按作业需求量划出一个分区装人该作业,作业执行完后,其所占的内存分区被收回,成为一个空闲区;如果该空闲区的相邻分区也是空闲区,则需要将相邻空闲区合并成一个空闲区;设计所才用的算法:采用最优适应算法,每次为作业分配内存时,总是把既能满足要求、又是最小的空闲分区分配给作业;但最优适应算法容易出现找到的一个分区可能只比作业所需求的长度略大一点的情行,这时,空闲区分割后剩下的空闲区就很小以致很难再使用,降低了内存的使用率;为解决此问题,设定一个限值minsize,如果空闲区的大小减去作业需求长度得到的值小于等于minsize,不再将空闲区分成己分分区和空闲区两部分,而是将整个空闲区都分配给作业;内存分配与回收所使用的结构体:为便于对内存的分配和回收,建立两张表记录内存的使用情况;一张为记录作业占用分区的“内存分配表”,内容包括分区起始地址、长度、作业名/标志为0时作为标志位表示空栏目;一张为记录空闲区的“空闲分区表”,内容包括分区起始地址、长度、标志0表空栏目,1表未分配;两张表都采用顺序表形式;关于分配留下的内存小碎片问题:当要装入一个作业时,从“空闲分区表”中查找标志为“1”未分配且满足作业所需内存大小的最小空闲区,若空闲区的大小与作业所需大小的差值小于或等于minsize,把该分区全部分配给作业,并把该空闲区的标志改为“0”空栏目;同时,在已分配区表中找到一个标志为“0”的栏目登记新装人作业所占用分区的起始地址,长度和作业名;若空闲区的大小与作业所需大小的差值大于minsize;则把空闲区分成两部分,一部分用来装入作业,另外一部分仍为空闲区;这时只要修改原空闲区的长度,且把新装人的作业登记到已分配区表中;内存的回收:在可变分区方式下回收内存空间时,先检查是否有与归还区相邻的空闲区上邻空闲区,下邻空闲区;若有,则将它们合件成一个空闲区;程序实现时,首先将要释放的作业在“内存分配表”中的记录项的标志改为“0”空栏目,然后检查“空闲区表”中标志为‘1’未分配的栏目,查找是否有相邻的空闲区,若有,将之合并,并修改空闲区的起始地址和长度;六:数据结构1已分配表的定义:struct{floataddress;//已分分区起始地址floatlength; //已分分区长度,单位为字节intflag; //已分配区表登记栏标志,"0"表示空栏目,实验中只支持一个字符的作业名}used_tablen; //已分配区表2空闲分区表的定义:struct{floataddress; //空闲区起始地址floatlength; //空闲区长度,单位为字节intflag; //空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配}free_tablem; //空闲区表3全局变量floatminsize=5;definen10 //假定系统允许的最大作业数量为ndefinem10 //假定系统允许的空闲区表最大为m七、核心算法://最优分配算法实现的动态分区intdistributeintprocess_name,floatneed_length{inti,k=-1; //k用于定位在空闲表中选择的未分配栏floatads,len;intcount=0;i=0;//核心的查找条件,找到最优空闲区whilei<=m-1//循环找到最佳的空闲分区{iffree_tablei.flag==1&&need_length<=free_tablei.length{count++;ifcount==1||free_tablei.length<free_tablek.lengthk=i;}i=i+1;}ifk=-1{iffree_tablek.length-need_length<=minsize//整个分配{free_tablek.flag=0;ads=free_tablek.address;len=free_tablek.length;}else{ //切割空闲区ads=free_tablek.address;len=need_length;free_tablek.address+=need_length;free_tablek.length-=need_length;}i=0;//循环寻找内存分配表中标志为空栏目的项whileused_tablei.flag=0{i=i+1;}ifi<=n-1//找到,在已分配区表中登记一个表项{used_tablei.address=ads;used_tablei.length=len;used_tablei.flag=process_name;count1++;}else//已分配区表长度不足{iffree_tablek.flag==0//将已做的整个分配撤销{free_tablek.flag=1;free_tablek.address=ads;free_tablek.length=len;}else//将已做的切割分配撤销{free_tablek.address=ads;free_tablek.length+=len;}cout<<"内存分配区已满,分配失败\n";return0;}}else{cout<<"无法为该作业找到合适分区\n";return0;}returnprocess_name;}八、程序流程图:作业分配流程图:内存回收流程图:九、程序说明:本程序采用VisualC++编写,模拟可变分区存储管理方式的内存分配与回收;假定系统允许的最大作业数量为n=10,允许的空闲区表最大项数为m=10,判断是否划分空闲区的最小限值为minsize=5;初始化用户可占用内存区的首地址为1000,大小为1024B;定义两个结构体及其对象free_tablem和used_tablen实现内存的分配回收及分配表和空闲表的登记;用最优分配算法实现动态分配时,调用intdistributeintprocess_name,floatneed_length内存分配函数,设定循环条件查找最佳空闲分区,定义intk以记录最佳空闲区的首地址,根据找到的空闲区大小和作业大小判断是整个分配给作业还是切割空闲区后再分配给作业,并在“内存分配表”和“空闲分区表”中作登记;调用intrecycleintprocess_name函数实现内存的回收;顺序循环“内存分配表”找到要回收的作业,将标志位设为“0”,定义floatrecycle_address,recycle_length;用recycle_address 记下回收作业的首地址,recycle_length记下回收作业长度;查找空闲表,如果free_tablei.address+free_tablei.length==recycle_address,说明有上邻接空闲区,这时上邻接区的起始地址不变,长度+recycle_address;如果recycle_address+recycle_length==free_tablei.address,说明有下邻接,这时下邻接空闲区的起始地址改为回收作业的起始地址recycle_address,长度+recycle_length;如果同时有上下邻接空闲区,则上邻接的起始地址不变,长度+recycle_address+下邻接的长度,下邻接标志设为“0”否则,要回收的内存没有邻接空闲区,在空闲区中找到一个标志为“0”的空栏目登记回收的内存;十、内存分配回收实现截图:1、后台代码的截图:1、假定系统内存分配表允许的最大作业项为10,当分配超过10时,提示“内存分配区已满,分配失败”;2、回收作业所占内存时,当输入的作业名不存在,回收失败,提示“该作业不存在”;3、当要释放某个作业时,将已分配表中此作业的标志置为‘0’,并在空闲区做相应登记;4、分配的作业大小21B与找到的最优空闲区大小25B差值小于5B,所以将整块空闲区直接分配给作业;5、分配的作业大小14B与找到的最优空闲区大小20B差值大于5B,所以将整块空闲区分割成两部分,然后修改空闲表;6、要回收的内存在空闲表中有上邻,将其合并7、空闲区有两个长度分别为20B和18B的未分配烂,现为作业6分配14B的内存,用最佳分配算法找到空闲区;2、制作界面的实现截图十、源程序:include<iostream.h>include<iomanip.h>//全局变量floatminsize=5;intcount1=0;intcount2=0;definem10 //假定系统允许的空闲区表最大为mdefinen10 //假定系统允许的最大作业数量为n//已分配表的定义struct{floataddress;//已分分区起始地址floatlength; //已分分区长度,单位为字节intflag; //已分配区表登记栏标志,"0"表示空栏目}used_tablen; //已分配区表对象名//空闲区表的定义:struct{floataddress; //空闲区起始地址floatlength; //空闲区长度,单位为字节intflag; //空闲区表登记栏标志,用"0"表示空栏目,用"1"表示未分配}free_tablem; //空闲区表对象名//函数声明voidinitializevoid;intdistributeint,float;intrecycleint;voidshow;//初始化两个表voidinitializevoid{inta;fora=0;a<=n-1;a++used_tablea.flag=0; //已分配表的表项全部置为空表项free_table0.address=1000;free_table0.length=1024;free_table0.flag=1; //空闲区表的表项全部为未分配}//最优分配算法实现的动态分区intdistributeintprocess_name,floatneed_length{inti,k=-1; //k用于定位在空闲表中选择的未分配栏floatads,len;intcount=0;i=0;whilei<=m-1//循环找到最佳的空闲分区{iffree_tablei.flag==1&&need_length<=free_tablei.length{count++;ifcount==1||free_tablei.length<free_tablek.lengthk=i;}i=i+1;}ifk=-1{iffree_tablek.length-need_length<=minsize//整个分配{free_tablek.flag=0;ads=free_tablek.address;len=free_tablek.length;}else{ //切割空闲区ads=free_tablek.address;len=need_length;free_tablek.address+=need_length;free_tablek.length-=need_length;}i=0;//循环寻找内存分配表中标志为空栏目的项whileused_tablei.flag=0{i=i+1;}ifi<=n-1//找到,在已分配区表中登记一个表项{used_tablei.address=ads;used_tablei.length=len;used_tablei.flag=process_name;count1++;}else//已分配区表长度不足{iffree_tablek.flag==0//将已做的整个分配撤销{free_tablek.flag=1;free_tablek.address=ads;free_tablek.length=len;}else//将已做的切割分配撤销{free_tablek.address=ads;free_tablek.length+=len;}cout<<"内存分配区已满,分配失败\n";return0;}}else{cout<<"无法为该作业找到合适分区\n";return0;}returnprocess_name;}intrecycleintprocess_name{inty=0;floatrecycle_address,recycle_length;inti,j,k; //j栏是下邻空闲区,k栏是上栏空闲区intx;//在内存分配表中找到要回收的作业whiley<=n-1&&used_tabley.flag=process_name{ y=y+1;}ify<=n-1//找到作业后,将该栏的标志置为‘0’{recycle_address=used_tabley.address;recycle_length=used_tabley.length;used_tabley.flag=0;count2++;}else//未能找到作业,回收失败{cout<<"该作业不存在\n";return0;}j=k=-1;i=0;whilei>=m||k=-1&&j=-1//修改空闲分区表{iffree_tablei.flag==1{ iffree_tablei.address+free_tablei.length==recycle_address k=i; //判断是否有上邻接ifrecycle_address+recycle_length==free_tablei.addressj=i; //判断是否有下邻接}i=i+1;}//合并空闲区ifk=-1//回收区有上邻接{ifj=-1{ //回收区也有下邻接,和上下领接合并free_tablek.length+=free_tablej.length+recycle_length;free_tablej.flag=0; //将第j栏的标记置为‘0’}else //不存在下邻接,和上邻接合并free_tablek.length+=recycle_length;}elseifj=-1{ //只有下邻接,和下邻接合并free_tablej.length+=recycle_length;free_tablej.address=recycle_address;}else{ //上下邻接都没有x=0;whilefree_tablex.flag=0x=x+1; //在空闲区表中查找一个状态为‘0’的栏目ifx<=m-1{ //找到后,在空闲分区中登记回收的内存free_tablex.address=recycle_address;free_tablex.length=recycle_length;free_tablex.flag=1;}else{ //空闲表已满,执行回收失败used_tabley.flag=process_name;cout<<"空闲区已满,回收失败\n";return0;}}returnprocess_name;}voidshow//程序执行时输出模拟的内存分配回收表{cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"+++++++空闲区+++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";forinti=0;i<=count2;i++cout<<"地址:"<<free_tablei.address<<""<<"作业长度:"<<free_tablei.length<<""<<"状态:"<<free_tablei.flag<<endl;cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"+++++++已分配区++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";forintj=0;j<count1;j++cout<<"地址:"<<used_tablej.address<<""<<"作业长度:"<<used_tablej.length<<""<<"作业名:"<<used_tablej.flag<<endl;}voidmain//主函数调用各功能函数对所有工作进行测试{intchoice;//用来选择将要进行的操作intjob_name;floatneed_memory;boolexitFlag=false;cout<<"动态分区分配方式的模拟\n";cout<<"\n";cout<<"请选择操作类型:\n";initialize;//开创空闲区和已分配区两个表whileexitFlag{cout<<"\n";cout<<"1:分配内存2:回收内存\n";cout<<"3:查看分配0:退出\n";cout<<"\n";cout<<"请输入您的操作:";cin>>choice;switchchoice{case0:exitFlag=true;//退出操作break;case1:cout<<"请输入作业名和所需内存:";cin>>job_name>>need_memory;distributejob_name,need_memory;//分配内存break;case2:intID;cout<<"请输入您要释放的分区号:";cin>>ID;recycleID;//回收内存break;case3:show;break;}}}十一、心得体会:每一次的实践,都会有很大的收获;决定做这个题目的时候,就针对此题要解决的几个问题反复思考,重新翻开教科书把相关内容特别是算法原理认真细致的看了一遍,设想会遇到的问题;在内存动态分配程序设计中,最优适应算法比首次要难一些,要加上对分配后该分区是否能最好地利用的判断;再一个问题是回收时候的合并,对地址的修改不是很有把握;着手写程序后,半天才理清回收的内存和上下邻合并的条件与关系,写此处的代码时,逻辑上比较混乱,反复错误反复修改了很多次才调试正确,这也是花了最多时间才得以正确实现的部分;之前大多用的c语言,对结构体,对象等知识淡忘了很多,这一次的实践让我找回了很多学过的知识点,也弥补了很多的不足之处;逻辑思维也得到了锻炼,写代码也不再像初学的时候那么繁琐,自己都能感觉到那一点点的进步,顿时也觉得充实起来;还有一个难点就是为作业找到最佳空闲区,此处是参照了一些资料后,理清了条件,然后用一个while两个if语句循环嵌套就实现了此功能;实践中也发现自身很多的不足,比如上理论课时认为已经理解了的算法原理在用代码实践时,发现还是有模糊和思考不周的地方;实践中最困难的是以前没有做过界面,所以虽然程序在大家的努力下还算顺利地完成了,功能测试也通过了,可是界面的制作却成了比较大的难题;好在之前在面向对象课程实验和程序设计课程设计中都用到过MFC,于是确定了用C++来制作界面;但是因为以前界面程序编写较少,所以界面的编写遇到了许多困难,特别是实现内存分配表和空闲分区表的输出遇到了很大的挫折,最后在查阅资料、认真思考的基础上实现内存分配表和空闲分区表的输出,并最终作出了内存管理子系统;在添加控件和消息映射的时候,问题不是很大,但是在对相应控件添加代码和给类添加成员函数的时候,要将源代码对应的部分添加进去,且要注意修包含的头文件;这些地方一直频繁出错,或在功能得不到实现,大家一起边找资料边学习新的知识,通过很多次的尝试,终于做出了界面,虽然不太好看,而且功能也很简单,但这也是也经过大家很大努力才完成的;学习着,收获着,并快乐着,这真是小组成员们共同的感触;对于自身不足的地方,大家也有了比较清晰的认识,对未来的发展,也有了个参照,将遇到的困难一个个跨过,并最终完成此次课程设计,真的感觉很有收获很有成就感;同时也培养了团队合作精神,几次的讨论,大大提升了我们合作的默契度,体会到合作的重要性;动手能力也得到了提高,当然,我们的设计还有很多的不足之处,有些问题没能很好解决,但通过不断学习和实践,我们一定会做的更好;。

可变分区存储管理方式的内存分配和回收

可变分区存储管理方式的内存分配和回收

free_quantity++; fscanf(文件指针,格式字符串,输入表列);}return 1;}return 0;}void sort(){int i,j,p;for(i=0;i<free_quantity-1;i++){p=i;for(j=i+1;j<free_quantity;j++){if(frees[j].address<frees[p].address){p=j;}}if(p!=i){frees[free_quantity]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantity];}}}void view(){int i;cout<<endl<<"mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"<< endl;cout<<"输出空闲区表:\n起始地址分区长度状态\n"<<endl;for(i=0;i<free_quantity;i++){(2);(12);cout<<frees[i].address;(10);cout<<frees[i].length;(8);cout<<frees[i].tag<<endl;}cout<<endl<<"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"< <endl;cout<<"输出已分分区表:\n起始地址分区长度占用作业名\n"<<endl;for(i=0;i<occupy_quantity;i++){(2);(12);cout<<occupys[i].address;(10);cout<<occupys[i].length;(8);cout<<occupys[i].tag<<endl;}}void ear(){char job_name[10];int job_length;int i,j,flag,t;cout<<"请输入分配内存的作业名和空间大小:";cin>>job_name;cin>>job_length;flag=0;for(i=0;i<free_quantity;i++){ ength>=job_length){flag=1;}}if(flag==0){ ength>=job_length){ddress=frees[i].address; ag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].address+=job_length;frees[i].length-=job_length;}else{for(j=i;j<free_quantity-1;j++){frees[j]=frees[j+1];}free_quantity--;cout<<"内存空间成功:)"<<endl;}}}void reclaim()ag,job_name)){flag=i;address=occupys[i].address;length=occupys[i].length;}}if(flag==-1){ ddress+frees[i].length)==address){if(((i+1)<free_quantity)&&(frees[i+1].address==address+length)){frees[i].length=frees[i].length+frees[i+1].length+length;for(j=i+1;j<free_quantity;j++){frees[j]=frees[j+1];}free_quantity--;p=1;}else{frees[i].length+=length;p=1;}}if(frees[i].address==(address+length)){frees[i].address=address;frees[i].length+=length;p=1;}}if(p==0){frees[free_quantity].address=address;frees[free_quantity].length=length;free_quantity++;}ddress=-1;ength=0;strcpy(frees[i].tag,"free");occupys[i].address=-1;ength=0;strcpy(occupys[i].tag,"");}free_quantity=0;occupy_quantity=0;flag=read();while(flag==1){sort();cout<<"选择功能项: (0-退出,1-分配内存,2-回收内存,3-显示内存)\n"<<endl;cout<<"选择功项(0-3):";cin>>chioce;switch(chioce){case 0:flag=0;break;case 1:ear();break;case 2:reclaim();break;case 3:view();break;default:cout<<"没有该选项\n"<<endl;}}}。

可变分区存储管理方式的内存分配和回收教程文件

可变分区存储管理方式的内存分配和回收教程文件
if((frees[i].address+frees[i].length)==address){
typedef struct node{
int address;
int length;
char tag[10];
}job;
job frees[MJ];
int free_quantity;
job occupys[MJ];
int occupy_quantity;
int read()
{
FILE *fp;
char fn[10];
}
cout<<endl<<"wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww"<<endl;
cout<<"输出已分分区表:\n起始地址分区长度占用作业名\n"<<endl;
for(i=0;i<occupy_quantity;i++){
int job_length;
int i,j,flag,t;
cout<<"请输入分配内存的作业名和空间大小:";
cin>>job_name;
cin>>job_length;
flag=0;
for(i=0;i<free_quantity;i++){ //寻找空间大于作业的空闲区登记项
if(frees[i].length>=job_length){
strcpy(occupys[occupy_quantity].tag,job_name);

计算机操作系统内存管理系统可变分区存储管理方式的内存分配回收

计算机操作系统内存管理系统可变分区存储管理方式的内存分配回收

计算机操作系统内存管理系统可变分区存储管理方式的内存分配回收内存管理是操作系统中非常重要的一个功能,它负责管理计算机内存资源的分配和回收。

内存分配是指在程序运行时,为进程分配适当大小的内存空间;内存回收是指当进程终止或不再需要分配的内存时,将它们释放回系统。

可变分区存储管理方式是一种常用的内存管理方式,它的特点是将内存分为若干个可变大小的分区。

下面将详细介绍可变分区存储管理方式的内存分配和回收。

一、内存分配:1. 首次适应算法(First Fit):从起始地址开始查找第一个满足分配要求的可用分区,分配其中一部分给进程,并将剩余部分作为新的可用分区。

2. 循环首次适应算法(Next Fit):与首次适应算法类似,但是从上一次分配的位置开始查找。

3. 最佳适应算法(Best Fit):在所有可用分区中找到最小且能满足分配要求的分区进行分配。

4. 最坏适应算法(Worst Fit):在所有可用分区中找到最大的空闲分区进行分配。

这种方法可能会造成大量外部碎片,但可以更好地支持大型进程。

二、内存回收:1.碎片整理:在每次回收内存时,可以通过将相邻的空闲分区合并为一个更大的分区来减少外部碎片。

这种方法需要考虑如何高效地查找相邻分区和合并它们。

2.分区分割:当一个进程释放内存时,生成的空闲分区可以进一步划分为更小的分区,并将其中一部分分配给新进程。

这样可以更好地利用内存空间,但会增加内存分配时的开销。

3.最佳合并:在每次回收内存时,可以选择将相邻的空闲分区按照最佳方式合并,以减少外部碎片。

4.分区回收:当一个进程终止时,可以将其所占用的分区标记为可用,以便其他进程使用。

三、优化技术:1.预分配内存池:为了避免频繁的内存分配和回收,可以预分配一定数量的内存作为内存池,由进程从内存池中直接分配和回收内存。

2.内存压缩:当内存不足时,可以通过将一部分进程的内存内容移动到磁盘等外部存储器中,释放出一定的内存空间。

3.页面替换算法:在虚拟内存系统中,当物理内存不足时使用页面替换算法,将不常用的页面淘汰出物理内存,以便为新页面分配内存。

主存空间的分配及回收 采用可变分区管理

主存空间的分配及回收 采用可变分区管理

主存空间的分配和回收采用可变分区管理1、采用可变分区管理,使用首次获最佳适应算法实现主存的分配和回收要求采用分区说明表进行。

提示:(1)可变式分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区个数是可以调整的。

当要装入一个作业时,根据作业需要的主存量,查看是否有足够的空闲空间,若有,则按需求量分割一部分给作业;若无,则作业等待。

随着作业的装入、完成,主存空间被分割成许多大大小小的分区。

有的分区被作业占用,有的分区空闲。

例如,某时刻主存空间占用情况如图3-1所示。

为了说明哪些分区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,如图3-2所示。

图3-1 内存空闲分区图图3-2 空闲区说明表其中,起始地址指出各空闲区的主存起始地址,长度指出空闲区的大小。

状态:未分配----该栏目记录的是有效的空闲区;空表目----没有登记信息。

由于分区数目不定,所以空闲区说明表中应有足够的空表目项。

否则造成溢出,无法登记。

同样,再设一个已分配区表,记录作业或进程的主存占用情况。

(2)当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。

有时找到的空闲区可能大于作业需求量,这时应将空闲区一分为二。

一个分给作业;另一个仍作为空闲区留在空闲区表中。

为了尽量减少由于分割造成的碎片,尽可能分配低地址部分的空闲区,将较大空闲区留在高地址端,以利于大作业的装入。

为此在空闲区表中,按空闲区首地址从低到高进行登记。

为了便于快速查找,要不断地对表格进行紧缩,即让“空表目”项留在表的后部。

(3)当一个作业执行完成时,作业所占用的分区应归还给系统。

在归还时要考虑相邻空闲区合并的问题。

作业的释放区与空闲区的邻接分以下四种情况考虑:① 释放区下邻(低地址邻接)空闲区;② 释放区上邻(高地址邻接)空闲区③ 释放区上下都与空闲区邻接;④ 释放区与空闲区不邻接。

(4)请按首次(或最佳)适应分配算法设计主存分配和回收程序。

可变分区存储管理方式的内存分配和回收

可变分区存储管理方式的内存分配和回收

可变分区存储管理方式的内存分配和回收第一篇:可变分区存储管理方式的内存分配和回收#include//定义输入/输出函数#include//数据流输入/输出#include//字符串处理#include//参数化输入/输出const int MJ=10;//假定系统允许的最大作业数量为10typedef struct node{int address;int length;char tag[10];}job;job frees[MJ];int free_quantity;job occupys[MJ];int occupy_quantity;int read(){FILE *fp;char fn[10];cout<cin>>fn;if((fp=fopen(fn,“r”))==NULL){ 其意义是在当前目录下打开文件file a,只允许进行“读”操作,并使fp指向该文件cout<}else{while(!feof(fp)){fscanf(fp,“%d,%d”,&frees[free_quantity].address,&frees[free_quantity].length);free_quantity++;fscanf(文件指针,格式字符串,输入表列);}return 1;}return 0;}void sort(){int i,j,p;for(i=0;ip=i;for(j=i+1;jif(frees[j].addressp=j;}}if(p!=i){frees[free_quantity]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantity];}}}void view(){int i;cout<cout<for(i=0;icout.setf(2); cout.width(12); cout<cout.width(10); cout<cout.width(8); cout<}cout<cout<for(i=0;icout.setf(2); cout.width(12); cout<cout.width(10); cout<cout.width(8); cout<}}void ear(){char job_name[10]; int job_length;int i,j,flag,t;cout<cin>>job_name; cin>>job_length; flag=0;for(i=0;iif(frees[i].length>=job_length){flag=1;}}if(flag==0){//未找到空闲区,返回cout<}else{t=0;i=0;while(t==0){if(frees[i].length>=job_length){//找到可用空闲区,开始分配t=1;}i++;}i--;occupys[occupy_quantity].address=frees[i].address;//修改已分配区表strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].address+=job_length;frees[i].length-=job_length;}else{for(j=i;jfrees[j]=frees[j+1];}free_quantity--;cout<}}}void reclaim()//回收作业所占的内存空间{char job_name[20];int i,j,flag,p=0;int address;int length;//寻找已分分区表中对应的登记项cout<cin>>job_name;flag=-1;for(i=0;iif(!strcmp(occupys[i].tag,job_name)){flag=i;address=occupys[i].address;length=occupys[i].length;}}if(flag==-1){ //在已分分区表中找不到作业cout<}else{//修改空闲区表,加入空闲表for(i=0;iif((frees[i].address+frees[i].length)==address){ if(((i+1)for(j=i+1;jfrees[j]=frees[j+1];}free_quantity--;p=1;}else{frees[i].length+=length;p=1;}}if(frees[i].address==(address+length)){ frees[i].address=address;frees[i].length+=length;p=1;}}if(p==0){frees[free_quantity].address=address; frees[free_quantity].length=length; free_quantity++;}//删除分配表中的该作业for(i=flag;ioccupys[i]=occupys[i+1];}occupy_quantity--;}}void main(){int flag=0;int t=1;int chioce=0;int i;for(i=0;ifrees[i].address=-1;//空闲区表初始化frees[i].length=0;strcpy(frees[i].tag,“free”);occupys[i].address=-1;//已分分区表初始化occupys[i].length=0;strcpy(occupys[i].tag,“");}free_quantity=0;occupy_quantity=0;flag=read();while(flag==1){sort();cout<cin>>chioce;switch(chioce){case 0:flag=0;break;case 1:ear();break;case 2:reclaim();break;case 3:view();break;default:cout<}}}第二篇:可变分区存储管理方式的内存分配和回收实验报告一.实验目的通过编写和调试存储管理的模拟程序以加深对存储管理方案的理解,熟悉可变分区存储管理的内存分配和回收。

可变分区的四种回收算法

可变分区的四种回收算法

可变分区的四种回收算法引言在操作系统中,内存管理是一个重要的任务。

在进行内存分配时,如果使用固定大小的分区,会导致内存碎片问题,导致大量的空闲内存无法被有效利用。

为了解决这一问题,可变分区管理算法被提出。

本文将详细探讨可变分区的四种回收算法,包括首次适应算法、最佳适应算法、最坏适应算法和快速适应算法。

一、首次适应算法首次适应算法是一种简单直观的内存分配算法。

它的思想是按照请求的顺序查找可用的空闲分区,并将其分配给请求的作业。

首次适应算法的具体步骤如下: 1. 遍历可用分区列表,查找第一个大于等于作业大小的空闲分区。

2. 如果找到了合适的分区,将作业分配给该分区,并更新分区表。

3. 如果没有找到合适的分区,作业将等待。

首次适应算法的优点是简单易懂,易于实现。

然而,它可能会导致较大的碎片和低内存利用率。

二、最佳适应算法最佳适应算法是一种更高效的内存分配算法。

它的思想是在可用分区中找到最小的适合作业大小的空闲分区,并将其分配给请求的作业。

最佳适应算法的具体步骤如下: 1. 遍历可用分区列表,找到最小的大于等于作业大小的空闲分区。

2. 如果找到了合适的分区,将作业分配给该分区,并更新分区表。

3. 如果没有找到合适的分区,作业将等待。

最佳适应算法的优点是可以减少碎片和提高内存利用率。

然而,它的查找过程可能更耗时,因为需要遍历所有的可用分区。

三、最坏适应算法最坏适应算法是一种与最佳适应算法相反的内存分配算法。

它的思想是在可用分区中找到最大的适合作业大小的空闲分区,并将其分配给请求的作业。

最坏适应算法的具体步骤如下: 1. 遍历可用分区列表,找到最大的大于等于作业大小的空闲分区。

2. 如果找到了合适的分区,将作业分配给该分区,并更新分区表。

3. 如果没有找到合适的分区,作业将等待。

最坏适应算法的优点是可以减少外部碎片的产生。

然而,它可能会导致大量的内部碎片和较低的内存利用率。

四、快速适应算法快速适应算法是一种结合了首次适应算法和最佳适应算法的内存分配算法。

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

实验报告操作系统可变分区存储管理方式的内存分配回收班级:XXXXXXXXXXXX学号:XXXXXXXXXXXX姓名:XXXXXX日期:XXXX.XX.XX版本历史Revisions History目录1引言41.1实验目的41.2参考文档42可变分区存储管理52.1实验原理分析52.2设计思路52.3源程序62.4重要结构体说明102.5重要变量说明102.6结果112.7测试方法对结果的分析112.8接口122.8.1接口设计说明122.9任务设计122.9.1流程图121 引言1.1实验目的通过首次适应算法、最佳适应算法和最坏适应算法实现主存空间的分配,可以使开发人员更好地理解存储分配算法。

1.2参考文档1.操作系统2.3.1节空闲存储区表2.操作系统2.3.2节首次适应法(1.分配算法,2.回收算法)2 可变分区存储管理2.1实验原理分析在可变分区模式下,在系统初启且用户作业尚未装入主存储器之前,整个用户区是一个大空闲分区,随着作业的装入和撤离,主存空间被分成许多分区,有的分区被占用,而有的分区时空闲的。

为了方便主存空间的分配和去配,用于管理的数据结构可由两张表组成:“已分配区表”和“未分配区表”。

在“未分配表中”将空闲区按长度递增顺序排列,当装入新作业时,从未分配区表中挑选一个能满足用户进程要求的最小分区进行分配。

这时从已分配表中找出一个空栏目登记新作业的起始地址和占用长度,同时修改未分配区表中空闲区的长度和起始地址。

当作业撤离时已分配区表中的相应状态变为“空”,而将收回的分区登记到未分配区表中,若有相邻空闲区再将其连接后登记。

2.2设计思路1、分配算法:采用首次适应法为作来分配大小为size的内存空间时,总是从表的起始端的低地址部分开始查找,当第一次找到大于或等于申请大小的空闲区时,就按所需大小分配给作业。

如果分配后原空闲区还有剩余空间,就修改原存储区表项的m_size和m_addr,使它记录余下的“零头”。

如果作业所需空间正好等于该空闲区大小,那么该空闲区表项的m_size就成为0,接下来要删除表中这个“空洞”,即将随后的各非零表项依次上移一个位置。

2、回收算法:当某一作业回收以前所分配到的内存时,就要将该内存区归还给系统,使其成为空闲区而可被其它作来使用。

回收时如释放区与邻近的空闲区相衔接,要将它们合并成较大的空闲区,否则空闲区将被分割得超来越小,最终导致不能利用;另外,空闲区个数越来越多,也会使空闲区登记表溢出。

2.3源程序/*| 如不会使用文件输入/输出,也不会使用I/O转向做输入和输出结果文件,| 可以手再抄输出结果后后再输到文件中,实验报告的文字内容由自己掌握,能多能少。

*/#include<stdio.h>#include<malloc.h>/*表的定义*/#define N 5#define MEMSIZE 1000typedefstruct map{unsigned m_size;char *m_addr;};struct map coremap[N];/* coremap表的初始化程序*/void initcoremap(char *addr, unsigned size){unsigned i;printf("init coremap, first addr: %d\n", addr);coremap[0].m_size = size;coremap[0].m_addr = addr;for(i = 1; i < N; i++){coremap[i].m_size = 0;coremap[i].m_addr = 0;}}/* 输出表的内容*/void printcoremap(void){unsigned i;/* 打印coremap表中各项的m_size和m_addr */for(i = 0; i < N; i++){printf("coremap[%d].m_addr=%d ", i, coremap[i].m_addr); printf("coremap[%d].m_size=%d\n", i, coremap[i].m_size); }}/* 首次适应的分配函数*/char *fmalloc(unsigned size){registerchar *a;registerstruct map *bp;for (bp = coremap; bp->m_size; bp++){if(bp->m_size >= size){a = bp->m_addr;bp->m_addr += size; /* 修改表项的首地址*/if((bp->m_size -= size) == 0) /* 有正好大小的空闲区*/ do{bp++;(bp - 1)->m_addr = bp->m_addr; /* 修改表项的首地址*/}while((bp - 1)->m_size = bp->m_size);/* 打印分配内存空间的m_size和m_addr*/printf("fmalloc size: %d, addr:%d\n", size, a);return(a);}}return(0);}/* 首次适应的回收函数*/void ffree(unsigned size, char *addr){struct map *bp;char *a, *t;unsigned tt;printf("ffree mem size=%u, addr=%u\n", size, addr);a = addr;for (bp = coremap; bp->m_addr <= a && bp->m_size != 0; bp++);if (bp > coremap && (bp - 1)->m_addr + (bp - 1)->m_size == a) /* 情况1、2 */ {(bp - 1)->m_size += size; /* 情况1*/if (a + size == bp->m_addr) /* 情况2*/{(bp - 1)->m_size += bp->m_size;while (bp->m_size){bp++;(bp - 1)->m_addr = bp->m_addr;(bp - 1)->m_size = bp->m_size;}}}else{if (a + size == bp->m_addr && bp->m_size) /* 情况3*/{bp->m_addr -= size;bp->m_size += size;}elseif (0 != size) /* 情况4*/{do{t = bp->m_addr;bp->m_addr = a;a = t;tt = bp->m_size;bp->m_size = size;bp++;}while (size = tt);}}}/* 主程序的框架*/int main(void){char *mymem;int size;int addr;char cmdchar;char c="";if ((mymem = malloc(MEMSIZE)) == NULL){printf("Not enough memory to allocate buffer\n"); exit(1);}initcoremap(mymem, MEMSIZE);while(c != 'q'){do{c = getchar();}while(c == '\n' || c == '\t' || c == ' ');cmdchar = c;switch (cmdchar){case'm':/* 分配空间*/scanf("%u", &size);fmalloc(size);break;case'f':/* 释放空间*/scanf("%u %u", &size, &addr);ffree(size, mymem + addr);break;case'p':printcoremap();break;default:/* 其它字母退出*/break;}}free(mymem);return 0;}2.4重要结构体说明空闲存储区表可采用结构数组的形式,采用的数据结构形式为:typedef struct map{unsigned m_size;char *m_addr;};m_size:是空闲分区的长度m_addr:是空闲分区的起始地址2.5重要变量说明coremap[N]:是空闲存储区表2.6结果2.7测试方法对结果的分析1、连续分配3个100长度的分区,剩下700长度的分区2、从头释放掉一个100长度的分区,里面有两个可用的分区,一个是100长度的分区,一个是700长度的分区3、程序运行的结果,与设计思路一致。

2.8接口2.8.1 接口设计说明2.9任务设计2.9.1 流程图。

相关文档
最新文档