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

课程设计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++来制作界面;但是因为以前界面程序编写较少,所以界面的编写遇到了许多困难,特别是实现内存分配表和空闲分区表的输出遇到了很大的挫折,最后在查阅资料、认真思考的基础上实现内存分配表和空闲分区表的输出,并最终作出了内存管理子系统;在添加控件和消息映射的时候,问题不是很大,但是在对相应控件添加代码和给类添加成员函数的时候,要将源代码对应的部分添加进去,且要注意修包含的头文件;这些地方一直频繁出错,或在功能得不到实现,大家一起边找资料边学习新的知识,通过很多次的尝试,终于做出了界面,虽然不太好看,而且功能也很简单,但这也是也经过大家很大努力才完成的;学习着,收获着,并快乐着,这真是小组成员们共同的感触;对于自身不足的地方,大家也有了比较清晰的认识,对未来的发展,也有了个参照,将遇到的困难一个个跨过,并最终完成此次课程设计,真的感觉很有收获很有成就感;同时也培养了团队合作精神,几次的讨论,大大提升了我们合作的默契度,体会到合作的重要性;动手能力也得到了提高,当然,我们的设计还有很多的不足之处,有些问题没能很好解决,但通过不断学习和实践,我们一定会做的更好;。
操作系统实验报告-可变分区存储管理方式的内存分配回收

实验三可变分区存储管理方式的内存分配回收一.实验目的(1)深入了解可变分区存储管理方式的内存分配回收的实现。
二.实验内容编写程序完成可变分区存储管理方式的内存分配回收,要求有内存空间分配表,并采用最优适应算法完成内存的分配与回收。
三.实验原理在可变分区模式下,在系统初启且用户作业尚未装入主存储器之前,整个用户区是一个大空闲分区,随着作业的装入和撤离,主存空间被分成许多分区,有的分区被占用,而有的分区时空闲的。
为了方便主存空间的分配和去配,用于管理的数据结构可由两张表组成:“已分配区表”和“未分配区表”。
在“未分配表中”将空闲区按长度递增顺序排列,当装入新作业时,从未分配区表中挑选一个能满足用户进程要求的最小分区进行分配。
这时从已分配表中找出一个空栏目登记新作业的起始地址和占用长度,同时修改未分配区表中空闲区的长度和起始地址。
当作业撤离时已分配区表中的相应状态变为“空”,而将收回的分区登记到未分配区表中,若有相邻空闲区再将其连接后登记。
可变分区的回收算法较为复杂,当一个作业撤离时,可分为4种情况:其临近都有作业(A和B),其一边有作业(A或B),其两边均为空闲区。
尤其重要的是,在程序中利用“new类型T(初值列表)”申请分配用于存放T类型数据的内存空间,利用“delete指针名”释放指针所指向的内存空间。
四.实验部分源程序#include <iostream>using namespace std;typedef struct SNode { // Space Nodeint start,end; // 起始,结束int length; // 长度大小struct SNode *next; // 指向下一结点的指针}* SP;SP Head=(SP)malloc(sizeof(SNode)); // 全局变量,内存空间头结void DispSpace() { // 显示内存空间分配情况SP p=Head->next;cout<<"\n 空闲区说明表\n"<<"---地址--长度---\n";while (p){cout<<" "<<p->start<<" "<<p->length<<endl;p=p->next;}cout<<"----------------\n";}void Initial() { // 初始化说明表SP p,q;p=(SP)malloc(sizeof(SNode));q=(SP)malloc(sizeof(SNode));p->start=14; p->length=12; p->end=26;q->start=32; q->length=96; q->end=128; // 指导书上的作业分配Head->next=p; // 与头结点连接p->next=q;q->next=NULL;DispSpace();}void Allocation(int len) { // 分配内存给新作业SP p=Head->next,q;while (p){if (p->length < len)p=p->next;else if (p->length > len){p->start=p->start+len;p->length=p->length-len;cout<<"分配成功!\n";DispSpace(); return;}else{//当两者长度相等q=p->next;p->next=q->next;cout<<"分配成功!\n";DispSpace(); return;}}cout<<"分配失败!\n";DispSpace(); return;}void CallBack(int sta,int len) { // 回收内存SP p=Head,q=p->next,r; // 开始地址和长度p->end=0;int en=sta+len;while (q) {if (sta == 0) { // 初始地址为0if (en == q->start) { // 正好回收q->start=0;q->length=q->end;return;}else {r=(SP)malloc(sizeof(SNode));r->start=sta; r->length=len; r->end=en;p->next=r;r->next=q;return;}}else if ((p->end < sta) && (q->start > en)) { // 上邻区r=(SP)malloc(sizeof(SNode));r->start=sta; r->length=len; r->end=en;p->next=r;r->next=q;return;}else if ((p->end < sta) && (q->start == en)) { // 邻区相接q->start=sta;q->length=q->end-sta;return;}else if ((p->end == sta) && (q->start < en)) { // 下邻区p->end=en;p->length=en-p->start;return;}else if (p->end==sta && q->start==en) { // 邻区相接p->end=q->end;p->length=p->end-p->start;p->next=q->next;return;}else {p=p->next;q=q->next;}}}void main() {Initial();cout<<"现在分配大小为6K 的作业4 申请装入主存: ";Allocation(6); // 分配时参数只有长度//--------指导书测试数据演示----------cout<<"现回收作业 3 (起址10,长度4)\n";CallBack(10,4);DispSpace();cout<<"现回收作业 2 (起址26,长度6)\n";CallBack(26,6);DispSpace();//---------------演示结束-------------system("pause");}五.实验结果与体会我的体会:下面红色部分是赠送的总结计划,不需要的可以下载后编辑删除!2014年工作总结及2015年工作计划(精选)XX年,我工区安全生产工作始终坚持“安全第一,预防为主,综合治理”的方针,以落实安全生产责任制为核心,积极开展安全生产大检查、事故隐患整改、安全生产宣传教育以及安全生产专项整治等活动,一年来,在工区全员的共同努力下,工区安全生产局面良好,总体安全生产形势持续稳定并更加牢固可靠。
可变分区存储管理代码

实验三可变分区存储管理方式的内存分配回收#include "iostream.h"#include "stdio.h"#include "stdlib.h"#include "conio.h"#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];//空闲区表int allocate(char J,float xk)//采用最有分配法分配xk大小的空间//char J;//float 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)//未找到可用空闲区,返回{cout<<"无可用空闲区"<<endl;return 0;}//找到可用空闲区,开始分配:若空闲区大小与分配的空间差小于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){cout<<"无表目填写已分分区,错误"<<endl;//xx空闲区表if(free_table[k].flag==0)//前面找到的是整个空闲区free_table[k].flag=1;else //前面找到的是某个空闲区的一部分free_table[k].length=free_table[k].length+xk;return 0;}else {used_table[i].address=ad;used_table[i].length=xk;used_table[i].flag=J;}return 1;}//内存分配函数结束}int reclaim(char J)//回收作业名为J的作业所占内存空间//char J;{int i,k,j,s,t;float S,L;//寻找已分分区表中对应登记项s=0;while((used_table[s].flag!=J||used_table[s].flag==0)&&s<n)s++;if(s>=n)//在已分分区表中找不到名字为J的作业{cout<<"找不到该作业"<<endl;return 0;}//修改已分分区表used_table[s].flag=0;//取得归还分区的起始地址S和xxLS=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;//找到下邻}i++;}if(k!=-1)if(j!=-1)//上邻空闲区,下邻空闲区,三项合并{free_table[k].length=free_table[j].length+free_table[k].length+L;free_table[j].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)//空闲区表满,回收空间失败,将已分分区表复原{cout<<"内存空闲表没有空间,回收空间失败"<<endl;used_table[s].flag=J;return 0;}free_table[t].address=S;free_table[t].length=L;free_table[t].flag=1;}return 1;}//内存归还函数结束void main(){int i,a;float xk;char J;//空闲区表初始化free_table[0].address=10240;free_table[0].length=102400;free_table[0].flag=1;for(i=1;i<m;i++)free_table[i].flag=0;//已分分区表初始化for(i=0;i<n;i++)used_table[i].flag=0;while(1){cout<<"选择功能项(0-推出,1-分配内存,2-回收内存,3-显示内存)"<<endl;cout<<"选择功项(0~3):";cin>>a;switch(a){case 0: exit(0);//a=0程序结束case 1://a=1分配内存空间cout<<"输入作业名J和作业所需长度xk:";cin>>J>>xk;allocate(J,xk);//分配内存空间break;case 2://a=2回收内存空间cout<<"输入要回收分区的作业名";cin>>J;reclaim(J);//回收内存空间case 3://a=3显示内存情况,输出空闲区表和已分分区表}cout<<"输出空闲区表:"<<endl;cout<<"起始地址分区长度标志"<<endl;for(i=0;i<m;i++)cout<<free_table[i].address<<free_table[i].length<<free_table[i].flag<<endl;cout <<"按任意键,输出已分分区表"<<endl;getch();cout<<"输出已分分区表:"<<endl;cout<<"起始地址分区长度标志"<<endl;for(i=0;i<n;i++)if(used_table[i].flag!=0)cout<<used_table[i].address<<used_table[i].length<<used_table[i].flag<<endl;elsecout<<used_table[i].address<<used_table[i].length<<used_table[i].flag<<endl; break;default:cout<<"没有该选项"<<endl;}}执行结果:选择0:选择1:。
可变分区存储管理方式的内存分配和回收教程文件

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)请按首次(或最佳)适应分配算法设计主存分配和回收程序。
可变分区分配与回收——采用最坏算法-操作系统课程设计

哈尔滨理工大学课程设计(操作系统)题目:可变分区分配与回收—采用最坏算法班级:计算机科学与技术学院计算机系10-8班姓名:张兢 1004010813指导教师:高雪瑶系主任:林克正2013年03月01日一、课程设计目的1、背景主存是CPU可直接访问的信息空间,合理而有效的使用贮存将在很大程度上影响整个计算机系统的性能。
本课题要求模拟实现分区式主存管理机制。
模拟实现各种分区管理方法以及相应的主存分配以及回收算法。
2、目的通过该课题进一步加深对可变分区存储机制的理解。
加深对存储器动态分区分配算法的认识。
掌握“首次适应算法”、“下次适应算法”、“最佳适应算法发”、“最坏适应算法”的内存分配过程。
掌握内存的回收策略。
二、课题任务描述1、设计可用的内存空闲空间,并能动态输入用户作业所需的内存大小。
2、编程模拟各种分配算法的实施过程,允许自行选择如“首次适应算法”、“下次适应算法”、“最佳适应算法发”、“最坏适应算法”等常用算法,要求实现不少于三种算法。
3、实现内存的回收。
要求考虑回收时的内存合并问题。
三、课题研发相关知识(包含所用库函数的介绍)1、首次适应算法(first fit)FF算法要求空闲分区链以地址递增的次序链接。
在分配内存时,从链首开始顺序查找,直至找到一个大小能男足要求的空闲分区位置;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。
若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。
但是,低址部分不断被划分,会留下许多难以利用的很小的空闲分区。
2、最佳适应算法(best fit)所谓“最佳”是指每次为作业分配内存时,总是把能满足要求、又是最小的空闲分区分配给作业,避免“大材小用”。
为了加速寻找,该算法要求将所有的空闲分区按其容量以从小到大的顺序形成一空闲分区链。
这样,第一次找到的能满足要求的空闲区,必然是最佳的。
这样,在存储器中会留下许多难以利用的小空闲区。
可变分区存储管理方案中的内存分配

可变分区存储管理方案中的内存分配/*(二)可变分区存储管理方案中的内存分配可变分区调度算法有:最先适应分配算法,最优适应分配算法,最坏适应算法用户提出内存空间的申请;系统根据申请者的要求,按照一定的分配策略分析内存空间的使用情况,找出能满足请求的空闲区,分给申请者;当程序执行完毕或主动归还内存资源时,系统要收回它所占用的内存空间或它归还的部分内存空间。
1.程序运行时首先接收输入:空闲区数据文件,包括若干行,每行有两个数据项:起始地址、长度(均为整数),各数据项以space隔开。
2.建立空闲区表并在屏幕上显示输出空闲区表内容,空闲区表中记录了内存中可供分配的空闲区的始址和长度,用标志位指出该分区是否是未分配的空闲区。
3.从用户界面根据用户提示接收一个内存申请,格式为:作业名、申请空间的大小。
4.按照最差(最坏)适配算法选择一个空闲区,分割并分配,修改相应的数据结构(空闲区表),填写内存已分配区表(起始地址、长度、标志位),其中标志位的一个作用是指出该区域分配给哪个作业。
5.重复3、4,直到输入为特殊字符(0)。
6.在屏幕上显示输出新的空闲区表和已分配区表的内容。
本程序包括:FIFO,最优适应分配算法,最坏适应算法input file:freememory.txtdata:10 1530 550 2080 12120 25160 18200 8VC++调试通过*/#include#include#include#includeconst int MAXJOB=100;//定义表最大记录数typedef struct node{int start;int length;char tag[20];}job;job frees[MAXJOB];//定义空闲区表int free_quantiry;//空闲区域的个数job occupys[MAXJOB];//定义已分配区表int occupy_quanity; //初始化函数void initial(){int i;for (i=0;i<maxjob;i++)< p="">{frees[i].start=-1;frees[i].length=0;strcpy(frees[i].tag,"free");occupys[i].start=-1;occupys[i].length=0;strcpy(occupys[i].tag,"");}free_quantiry=0;occupy_quanity=0;}//读数据函数int readData(){FILE *fp;char fname[20];cout<<"请输入初始空闲表文件名:"<<endl;< p="">cin>>fname;if ((fp=fopen(fname,"r"))==NULL){cout<<"错误,文件打不开,请检查文件名"<<endl;< p="">}else{while(!feof(fp)){fscanf(fp,"%d %d",&frees[free_quantiry].start,&frees[free_qu antiry].length);free_quantiry++;}return 1;}return 0;}//sortvoid sort()//按空闲区起始地址排序{int i,j,p;for (i=0;i<free_quantiry;i++)< p="">{p=i;for (j=i+1;j<free_quantiry;j++)< p="">{if (frees[j].start<frees[p].start)< p="">{p=j;}}if (p!=i){frees[free_quantiry]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantiry];}}}//显示函数void view(){int i;cout<<endl<<"----------------------------------------------------------"<<endl;< p="">cout<<"当前空闲表:"<<endl;< p="">cout<<"起始地址长度状态"<<endl;< p="">for(i=0;i<free_quantiry;i++)< p="">{cout.setf(2);cout.width(12);cout<<frees[i].start;< p="">cout.width(10);cout<<frees[i].length;< p="">cout.width(8);cout<<frees[i].tag<<endl;< p="">}cout<<endl<<"-----------------------------------------------"<<endl;< p="">cout<<"当前已分配表:"<<endl;< p="">cout<<"起始地址长度占用作业名"<<endl;< p="">for (i=0;i<occupy_quanity;i++)< p="">{cout.setf(2);cout.width(12);cout<<occupys[i].start;< p="">cout.width(10);cout<<occupys[i].length;< p="">cout.width(8);cout<<occupys[i].tag<<endl;< p="">}}//最优适应分配算法void best_fit(){char job_name[20];int job_length;int i,j,flag,t;cout<<"请输入新申请内存空间的作业名和空间大小:"<<endl;< p="">cin>>job_name;cin>>job_length;flag=0;for (i=0;i<free_quantiry;i++)< p="">{if (frees[i].length>=job_length){flag=1;}}if (flag==0){cout<<"Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试"<<="">else{t=0;i=0;while(t==0){if (frees[i].length>=job_length){t=1;}i++;}i--;for (j=0;j<free_quantiry;j++)< p="">if((frees[j].length>=job_length)&&frees[j].length<frees[i].length) < p="">{i=j;}}occupys[occupy_quanity].start=frees[i].start;strcpy(occupys[occupy_quanity].tag,job_name);occupys[occupy_quanity].length=job_length;occupy_quanity++;if (frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length;}else{for (j=i;j<free_quantiry-1;j++)< p="">{frees[j]=frees[j+1];}free_quantiry--;cout<<"内存分配成功"<<endl;< p="">}}}//撤销作业void finished()char job_name[20];int i,j,flag,p=0;int start;int length;cout<<"请输入要撤销的作业名:"<<endl;< p="">cin>>job_name;flag=-1;for (i=0;i<occupy_quanity;i++)< p="">{if (!strcmp(occupys[i].tag,job_name)){flag=i;start=occupys[i].start;length=occupys[i].length;}}if (flag==-1){cout<<"没有这个作业"<<endl;< p="">}else{for (i=0;i<free_quantiry;i++)< p="">{if ((frees[i].start+frees[i].length)==start){if(((i+1)<free_quantiry)&&(frees[i+1].start==start+length))< p=""> {frees[i].length=frees[i].length+frees[i+1].length; for (j=i+1;j<free_quantiry;j++)< p="">{frees[j]=frees[j+1];}free_quantiry--;p=1;}else{frees[i].length+=length;p=1;}}if (frees[i].start==(start+length)){frees[i].start=start;frees[i].length+=length;p=1;}}if (p==0){frees[free_quantiry].start=start;frees[free_quantiry].length=length;free_quantiry++;}for (i=flag;i<occupy_quanity;i++)< p="">{occupys[i]=occupys[i+1];}occupy_quanity--;}}//显示版权信息函数void version(){cout<<endl<<endl;< p="">cout<<" ┏━━━━━━━━━━━━━━━━━━━━━━━┓"<<endl;< p="">cout<<" ┃可变分区存储管理方案中的内存分配┃"<<endl;< p="">cout<<" ┠───────────────────────┨"<<endl;< p="">cout<<" ┃siqingyang ┃"<<endl;< p="">cout<<" ┃version 2011 build 0520┃"<<endl;< p="">cout<<" ┗━━━━━━━━━━━━━━━━━━━━━━━┛"<<endl;< p="">cout<<endl<<endl;< p="">}void main(){int flag=0;int t=1;int chioce=0;version();initial();flag=readData();view();while(flag==1){sort();cout<<endl<<endl<<"===================================================="<<endl;</p><p>cout<<" p="" 可变分区存储管理模拟系统"<<endl;<="">cout<<"================================= ========================"<<="" p="">cout<<" 1.best fit申请空间2.撤消作业0.退出"<<endl;< p=""> cout<<"请选择:";cin>>chioce;switch(chioce){case 1:best_fit();view();break;case 2:finished();view();break;case 0:flag=0;break;default:cout<<"选择错误!"<<endl;< p="">}}}</endl;<></endl;<></endl<<endl<<"========================== ========================></endl<<endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl;<></endl<<endl;<></occupy_quanity;i++)<></free_quantiry;j++)<></free_quantiry)&&(frees[i+1].start==start+length))<> </free_quantiry;i++)<></endl;<></occupy_quanity;i++)<></endl;<></endl;<></free_quantiry-1;j++)<></frees[i].length)<></free_quantiry;j++)<></free_quantiry;i++)<></endl;<></occupys[i].tag<<endl;<></occupys[i].length;<></occupys[i].start;<></occupy_quanity;i++)<></endl;<></endl;<></endl<<"-----------------------------------------------"<<endl;<></frees[i].tag<<endl;<></frees[i].length;<></frees[i].start;<></free_quantiry;i++)<></endl;<></endl;<></endl<<"----------------------------------------------------------"<<endl;<></frees[p].start)<></free_quantiry;j++)<></free_quantiry;i++)<></endl;<></endl;<></maxjob;i++)<>。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
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;
}
}
}。