首次适应算法实验报告材料
存储器管理实验实验报告
存储器管理实验实验报告一、实验目的存储器管理是操作系统的重要组成部分,本次实验的目的在于深入理解存储器管理的基本原理和方法,通过实际操作和观察,掌握存储器分配与回收的算法,以及页面置换算法的实现和性能评估。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C++,开发工具为 Visual Studio 2019。
三、实验内容与步骤(一)存储器分配与回收算法实现1、首次适应算法(1)原理:从空闲分区链的首地址开始查找,找到第一个满足需求的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态(已分配或空闲)。
当有分配请求时,从链表头部开始遍历,找到第一个大小满足需求的空闲分区。
将该分区进行分割,一部分分配给请求,剩余部分仍作为空闲分区留在链表中。
若找不到满足需求的空闲分区,则返回分配失败。
2、最佳适应算法(1)原理:从空闲分区链中选择与需求大小最接近的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态。
当有分配请求时,遍历整个链表,计算每个空闲分区与需求大小的差值。
选择差值最小的空闲分区进行分配,若有多个差值相同且最小的分区,选择其中起始地址最小的分区。
对选中的分区进行分割和处理,与首次适应算法类似。
3、最坏适应算法(1)原理:选择空闲分区链中最大的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态。
当有分配请求时,遍历链表,找到最大的空闲分区。
对该分区进行分配和处理。
(二)页面置换算法实现1、先进先出(FIFO)页面置换算法(1)原理:选择在内存中驻留时间最久的页面进行置换。
(2)实现步骤:建立页面访问序列。
为每个页面设置一个进入内存的时间戳。
当发生缺页中断时,选择时间戳最早的页面进行置换。
2、最近最久未使用(LRU)页面置换算法(1)原理:选择最近一段时间内最长时间未被访问的页面进行置换。
实验三 最佳适应算法 实验报告
最佳适应算法实验报告一、实验目的了解首次适应算法、最佳适应方法、最差适应算法二、实验方法修改Minix操作系统的内存分配源码,实现最佳适应算法三、实验任务修改Minix操作系统中的内存分配源码,将首次适应算法更改为最佳适应算法。
重新编译系统映像文件,观察实验结果。
四、实验要点内存分配、首次适应算法、最佳适应算法。
五、实验内容5.1 minix内存分配源码安装好minix操作系统以后,minix系统的源码位于/usr/src目录中。
其中,与内存分配的相关源码则在/usr/src/servers/pm/alloc.c中。
minix系统初始的内存分配算法为首次适应算法。
在minix系统中,空闲的内存空间信息采用链表的信息储存起来,而操作系统分配内存空间的过程则是在这个链表中寻找一个合适空间,返回内存空间的地址,再更改链表中的内存空间信息。
这就是minix系统分配内存的实质。
5.2分析首次适应算法首次适应算法,指的从空闲内存块链表的第一个结点开始查找,把最先找到的满足需求的空闲内存块分配出去。
这种算法的优点是分配所需的时间较短,但这种算法会形成低地址部分形成很多的空间碎片,高地址区保留大量长度较长的空闲内存块。
内存分配的操作在/usr/src/servers/pm/alloc.c源文件中的alloc_mem函数中完成。
在函数的初始位置,定义了两个用于遍历链表的指针变量,两个指针变量的定义如下:registerstruct hole *hp, *prev_ptr;而hole结构体的定义如下:PRIVATE struct hole {struct hole *h_next;phys_clicksh_base;phys_clicksh_len;} hole[NR_HOLES];先分析这个结构体的定义,这个结构体中,有三个变量,h_next是一个指向链表下一个结点的指针变量;h_base则是指向这个链表所表示的空闲内存空间的地址,h_len 则是这个空闲内存空间的长度;phys_clicks的定义可以在/usr/src/include/minix/type.h 中找到,phys_clicks的定义为:typedef unsigned intpyhs_clicks;phys_clicks其实就是无符号的整数类型。
可变分区首次适应算法
可变分区首次适应算法--操作系统实验报告题目:可变分区首次适应算法指导老师:班级:姓名:学号:时间:实验三可变分区首次适应算法一、实验目的模拟内存分配, 了解并掌握动态分区分配中所用的数据结构、分区分配算法。
回顾链表的创建,插入,删除等基本操作;深刻理解首次适应内存分配算法。
二、实验内容编程实现首次适应内存分配算法,并上机验证。
实验环境:Microsoft Visual Studio 2010三、算法描述该程序用一个链表来模拟内存的空间分布。
从键盘输入链表长度和第一个结点的首地址、以及其他各个结点所占空间大小。
然后进行申请空间,并判断所申请的大小是否符合要求,能不能进行分配。
本程序主要包括两大模块,一是建立链表模块,二是申请并分配空间模块。
四、程序清单及简单注释// 内存分配算法:#include<iostream>#include<stdlib.h>#include <conio.h>using namespace std;int size=0,count=0,part[1000],address[1000],flag[1000];//设定全局变量//*******************输出可视结果*****************//void Output(){int j;cout<<" 输出内存分配情况:"<<endl;cout<<endl;cout<<" | 分区号| 分区大小| 起始地址| 状态|"<<endl;for(j=1;j<=count;j++){cout<<" | "<<j<<" ";cout<<" | "<<part[j]<<" ";cout<<" | "<<address[j]<<" ";if(flag[j]==1)cout<<" | "<<"已分配";if(flag[j]==0)cout<<" | "<<"未分配";cout<<" |";cout<<endl;}}//******************创建原始环境******************//void Create()//指明内存空间并初步地为作业分配内存{int i=1,m=0,s=0,start=0;char contin='Y';cout<<"请输入待分配的内存大小:";cin>>size;cout<<endl;cout<<"开始为作业分配内存空间"<<endl;cout<<endl;cout<<"请输入第一次分区的首地址:";cin>>start;cout<<endl;cout<<"输入每个分区的大小,以‘Y’继续操作,以‘N’结束分区操作:"<<endl; cout<<endl;while(contin!='N'){count=i;cout<<"请输入第"<<i<<"个作业的大小:";cin>>part[i];address[i]=start;start=start+part[i];s=m;//m用来标记已分配内存的总的大小,s用来标记m之前的值m=m+part[i];flag[i]=1;//标识内存已分配if(m==size){cout<<endl;cout<<"已分配完所有内存空间,请结束操作!"<<endl;cout<<endl;contin='N';}if(m<size){cout<<endl;cout<<"是否继续? Y/N:";cin>>contin;cout<<endl;while(contin!='Y'&&contin!='N'){cout<<endl;cout<<"输入‘N’或‘Y’继续操作:";cin>>contin;cout<<endl;}if(contin=='Y')i++;if(contin=='N')//如果不继续分配内存,将剩余的空间定义为一个分区,但标记为未分配{part[++i]=size-m;count=i;//分区总数address[i]=start;//起始地址}}//if(m<size)if(m>size){cout<<endl;cout<<"申请空间超出未分配的空间大小,是否重新分配?Y/N:";cin>>contin;cout<<endl;if(contin=='N'){ flag[i]=0;part[i]=size-s;}else{start=start-part[i];//如果重新分配,恢复原来的起始地址m=s;flag[i]=0;}}//if(m>size)}//while}//**************************分配内存********************//void Distribute(){int tag=0,space=0,i,j,situation=0;//situation用来表示分配是否成功cout<<endl;cout<<"输入作业所需的内存空间:";cin>>space;cout<<endl;for(i=1;i<=count;i++){if(part[i]==space&&flag[i]==0){flag[i]=1;Output();situation=1;break;}if(part[i]>space&&flag[i]==0){flag[i]=1;cout<<"分配成功!"<<endl;cout<<endl;for(j=count+1;j>=i+2;j--){part[j]=part[j-1];flag[j]=flag[j-1];}flag[i+1]=0;//多余的内存部分状态为未分配part[i+1]=part[i]-space;part[i]=space;//划出一部分内存空间分配给作业flag[count+1]=0;++count;//重新定义分区的首地址for(j=1;j<count;j++){address[j+1]=address[j]+part[j];}Output();situation=1;break;}}if(situation==0){cout<<"分配失败!"<<endl;cout<<endl;for(j=1;j<=count;j++)//判断是什么原因造成分配失败{if(flag[j]==0){tag=1;break;}}if(tag==1)cout<<"所有的空间大小都不足以分配!"<<endl<<endl;if(tag==0)cout<<"所有的空间均已分配!"<<endl<<endl;;Output();}}//********************回收分配出去的内存**********************// void Restore(){int tag=0,i,j,m=0,k;for(i=1;i<=count;i++){if(flag[i]==1){tag=1;break;}}if(tag==0)//回收前进行判断内存是否已经被分配{cout<<endl;cout<<"所有分区均未分配,不需要回收操作!"<<endl; }if(tag==1){cout<<endl;cout<<"请输入要回收的分区号:";cin>>j;flag[j]=0;//回收分区//如果有几段连续的空闲分区,则将他们合并for(i=count;i>1;i--){if(flag[i]==0&&flag[i-1]==0){m++;//用以标记将被撤销的分区块数part[i-1]=part[i-1]+part[i];part[i]=0; //先将后一个分区的大小和地址置空address[i]=0;}}for(i=count;i>=1;i--){if(address[i]!=0){ k=i; break;}elsecount--;}//处理末位连续的空闲分区for(i=k;i>1;i--)//处理中间的连续的空闲分区{if(address[i]==0){for(j=i;j<k;j++){part[j]=part[j+1];address[j]=address[j+1];flag[j]=flag[j+1];}--count;//撤销一个区分,总数减一}}Output();}}//********************主函数*********************//void main(){int i;char ch='y',s;cout<<endl<<endl<<"\t\t\t可变分区首次适应算法"<<endl<<endl;cout<<endl;for(i=0;i<1000;i++){part[i]=0;address[i]=0;//初始化数组的值flag[i]=0;}Create();Output();while(ch=='y'||ch=='Y'){cout<<endl;cout<<"选择操作,回收内存(R)或继续分配(D):";cin>>s;while(s!='R'&&s!='D'){cout<<endl;cout<<"请选择正确地操作,回收内存请输入R,继续分配请输入D:";cin>>s;}if(s=='R'){ Restore(); cout<<endl;}if(s=='D'){ Distribute(); cout<<endl;}cout<<"是否继续操作!是请输入'y'或'Y',否请输入任意字符以结束程序:";cin>>ch;}cout<<endl;cout<<"本程序结束执行!"<<endl;}五、实验结果建立内存分配环境:剩余空间不足以分配:所有的空间均已分配:回收分区1:回收分区2,由于两个空闲分区连续,将合并区分1和分区2:六、实验小结本算法从链首开始查找可以满足请求申请的空间大小的第一个结点,然后按照请求的大小,从该结点空间中划分一块适当的空间分配,剩下的空间作为一个新的结点接到后面。
操作系统存储管理实验报告
操作系统存储管理实验报告一、实验目的本次实验的目的是通过编写一段程序,实现对内存的分配和回收操作,并验证算法的正确性和性能。
二、实验内容1.实现首次适应算法首次适应算法是一种动态分配的内存管理算法,通过从低地址往高地址内存块,找到第一个满足需求的空闲块进行分配。
具体实现过程如下:(1)初始化内存空间,设置内存块的大小和地址范围;(2)编写一个函数,实现内存的分配操作,根据需求大小找到第一个合适的空闲块,并在其前后设置相应的标志位;(3)编写一个函数,实现内存的回收操作,根据释放块的地址,将其前后的标志位进行合并;(4)模拟应用程序的运行,测试内存的分配和回收操作。
2.实现最佳适应算法最佳适应算法是一种动态分配的内存管理算法,通过整个内存空间,找到最小的满足需求的空闲块进行分配。
具体实现过程如下:(1)初始化内存空间,设置内存块的大小和地址范围;(2)编写一个函数,实现内存的分配操作,遍历整个内存空间,找到满足需求且大小最小的空闲块进行分配;(3)编写一个函数,实现内存的回收操作,根据释放块的地址,将其前后的标志位进行合并;(4)模拟应用程序的运行,测试内存的分配和回收操作。
三、实验结果1.首次适应算法经过测试,首次适应算法能够正确地进行内存的分配和回收操作,并且算法的性能良好。
尽管首次适应算法在分配过程中可能会产生碎片,但是由于它从低地址开始,可以在较短的时间内找到满足需求的空闲块。
在实际应用中,首次适应算法被广泛采用。
2.最佳适应算法经过测试,最佳适应算法能够正确地进行内存的分配和回收操作,并且算法的性能较好。
最佳适应算法会整个内存空间,找到大小最小的满足需求的空闲块。
因此,在分配过程中不会产生很多的碎片,但是算法的执行时间较长。
四、实验总结通过本次实验,我们成功地实现了首次适应算法和最佳适应算法,并对算法的正确性和性能进行了验证。
两种算法在内存的分配和回收过程中都表现出良好的性能,可广泛应用于实际场景中。
首次适应算法实验报告
操作操作系统大作业题目:首次适应算法分配内存学号: **********学生姓名:***班级:计科121首次适应算法分配内存一、问题描述在内存分配中,动态分区是根据实际的进程需求,动态地为之分配空间。
而首次适应算法分配时从表头指针开始查找可利用空间表,将找到的第一个大小不小于“请求”的空闲块的一部分分配给用户。
可利用空间表本身既不按节点的初始地址有序,也不按节点的大小有序。
用户释放内存,回收时只是将空闲块插入在链表的表头即可,此算法比较节省时间。
二、运行环境 VC6.0三、算法思想。
首次适应算法要求空闲分区链以地址递增的次序链接。
在分配内存时,从链首开始查找,直到找到一个大小能满足要求的空闲分区为止;然后按照作业大小,从该分区中划出一块内存空间分配给请求者,余下的空闲区仍留在空闲链中。
若从链首到链尾都不能找到一个能满足要求的分区,则此次分配失败。
四、实验目的在计算机系统中,为了提高内存区的利用率,必须给电脑内存区进行合理的分配。
本实验通过对内存区分配方法首次适应算法的使用,来了解内存分配的模式。
五、首次适应算法分配内存算法概要(1)结构体Typedef struct freearea//定义一个空闲区说明表结构{ long size; //分区大小long address; //分区地址int state; //状态}ElemType; // 线性表的双向链表存储结构Typedef struct DuLNode{ ElemType data;structDuLNode *prior; //前趋指针structDuLNode *next; //后继指针} DuLNode,*DuLinkList;Status Initblock(intMAX_length)//开创带头结点的内存空间链表{ 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; //尾结点的地址是0block_last->data.size=MAX_length; //分区大小是最大分区block_last->data.state=Free; //状态是空return OK; }(2)主要函数说明:void alloc();进行内存分配的功能函数。
实验四操作系统存储管理实验报告
实验四操作系统存储管理实验报告一、实验目的本次实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配与回收、页面置换算法等关键概念,并能够分析和解决存储管理中可能出现的问题。
二、实验环境本次实验在装有 Windows 操作系统的计算机上进行,使用了 Visual Studio 等编程工具和相关的调试环境。
三、实验内容(一)内存分配与回收算法实现1、首次适应算法首次适应算法从内存的起始位置开始查找,找到第一个能够满足需求的空闲分区进行分配。
在实现过程中,我们通过建立一个空闲分区链表来管理内存空间,每次分配时从表头开始查找。
2、最佳适应算法最佳适应算法会选择能够满足需求且大小最小的空闲分区进行分配。
为了实现该算法,在空闲分区链表中,分区按照大小从小到大的顺序排列,这样在查找时能够快速找到最合适的分区。
3、最坏适应算法最坏适应算法则选择最大的空闲分区进行分配。
同样通过对空闲分区链表的排序和查找来实现。
(二)页面置换算法模拟1、先进先出(FIFO)页面置换算法FIFO 算法按照页面进入内存的先后顺序进行置换,即先进入内存的页面先被置换出去。
在模拟过程中,使用一个队列来记录页面的进入顺序。
2、最近最久未使用(LRU)页面置换算法LRU 算法根据页面最近被使用的时间来决定置换顺序,最近最久未使用的页面将被置换。
通过为每个页面设置一个时间戳来记录其最近使用的时间,从而实现置换策略。
3、时钟(Clock)页面置换算法Clock 算法使用一个环形链表来模拟内存中的页面,通过指针的移动和页面的访问标志来决定置换页面。
四、实验步骤(一)内存分配与回收算法的实现步骤1、初始化内存空间,创建空闲分区链表,并为每个分区设置起始地址、大小和状态等信息。
2、对于首次适应算法,从链表表头开始遍历,找到第一个大小满足需求的空闲分区,进行分配,并修改分区的状态和大小。
3、对于最佳适应算法,在遍历链表时,选择大小最接近需求的空闲分区进行分配,并对链表进行相应的调整。
操作系统 首次最佳适应算法
学号专业姓名实验日期教师签字成绩实验报告【实验名称】采用可变式分区管理,使用首次获最佳适应算法实现内存分配与回收【实验目的与原理】1、理解首次获最佳适应算法的内涵,并熟练掌握该算法。
2、学会可变式分区管理的原理是即在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区个数是可以调整的。
3、当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区没有时应将空闲区一分为二。
为了便于快速查找,要不断地对表格进行紧缩,即让“空表目”项留在表的后部。
4、当一个作业执行完成时,作业所占用的分区应归还给系统。
作业的释放区与空闲区的邻接分以下四种情况考虑:①释放区下邻(低地址邻接)空闲区;②释放区上邻(高地址邻接)空闲区③释放区上下都与空闲区邻接;④释放区与空闲区不邻接。
【实验内容】#include<stdio.h>#include<iostream>#include<string>using namespace std;const int MAXJOB=100;//定义表最大记录数typedef struct node{int front;int length;char data[20];}job;job frees[MAXJOB];//定义空闲区表int free_quantity;job occupys[MAXJOB];//定义已分配区表int occupy_quantity;//初始化函数void initial(){int i;for(i=0;i<MAXJOB;i++){frees[i].front=-1;frees[i].length=0;strcpy(frees[i].data,"free");occupys[i].front=-1;occupys[i].length=0;strcpy(occupys[i].data," ");}free_quantity=0;occupy_quantity=0;}//创建空闲分区表int creatfree(){FILE *fp;char fname[20];cout<<"请输入空闲区数据文件来源的文件名:"; cin>>fname;if((fp=fopen(fname,"r"))==NULL){cout<<"错误,文件打不开,请检查文件名"<<endl; }else{while(!feof(fp)){fscanf(fp,"%d\t%d\n",&frees[free_quanti ty].front,&frees[free_quantity].length);free_quantity++;}cout<<"空闲的分区表已建立!\n";return 1;}return 0;}void sort()//将free空间安首地址从小到大的顺序排列{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].front<frees[p].front){p=j;}}if(p!=i){frees[free_quantity]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantity];}}}//显示函数void show(){int i;cout<<endl<<"----------------------------------------------------------"<<endl;cout<<"当前空闲表:"<<endl;cout<<" 起始地址长度状态"<<endl;for(i=0;i<free_quantity;i++){cout.setf(2);cout.width(12);cout<<frees[i].front;cout.width(10);cout<<frees[i].length;cout.width(8);cout<<frees[i].data<<endl;}cout<<endl<<"----------------------------------------------------------"<<endl;cout<<"当前已分配表:"<<endl;cout<<" 起始地址长度占用作业名"<<endl;for(i=0;i<occupy_quantity;i++){cout.setf(2);cout.width(12);cout<<occupys[i].front;cout.width(10);cout<<occupys[i].length;cout.width(8);cout<<occupys[i].data<<endl;}cout<<endl<<"----------------------------------------------------------"<<endl;}//最先适应分配算法void assign(){char job_name[20];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)//如果空闲空间I的长度〉作业长度{flag=1; //空闲标志位就置1 }}if(flag==0){cout<<endl<<"对不起,当前没有能满足你申请长度的空闲内存,请稍候再试!"<<endl;}else{t=0;i=0;while(t==0)//为空闲区间的时候{if(frees[i].length>=job_length){t=1;}i++;//如果空闲空间I的长度不大于作业长度,I加一,判断下一个空间}i--;occupys[occupy_quantity].front=frees[i] .front;strcpy(occupys[occupy_quantity].data,jo b_name);occupys[occupy_quantity].length=job_len gth;occupy_quantity++;if(frees[i].length>job_length)//如果空间的长度大于作业的长度,{frees[i].front+=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 cancel(){char job_name[20];int i,j,flag,p=0;int front;int length;cout<<"请输入要撤消的作业名:";cin>>job_name;flag=-1;for(i=0;i<occupy_quantity;i++){if(!strcmp(occupys[i].data,job_name))//当输入作业名匹配时{flag=i;front=occupys[i].front;length=occupys[i].length;}}if(flag==-1){cout<<"没有这个作业名"<<endl;}else{//加入空闲表for(i=0;i<free_quantity;i++){if((frees[i].front+frees[i].length)==fr ont)//上空{if(((i+1)<free_quantity)&&(frees[i+1].f ront==front+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].front==(front+length))//下空上不空{frees[i].front=front;frees[i].length+=length;//第i 个空闲区间的长度=第i个空闲区间的长度+lengthp=1;}}if(p==0)//上下空闲区都不空{frees[free_quantity].front=front;frees[free_quantity].length=length;free_quantity++;}//删除分配表中的该作业for(i=flag;i<occupy_quantity;i++){occupys[i]=occupys[i+1];}occupy_quantity--;}}void main(){int flag=0;int t=1;int chioce=0;cout<<"*********** xxxxxxxxx***********\n"; initial();flag=creatfree();while(flag==1){sort();cout<<" 可变分区存储管理模拟系统"<<endl;cout<<" 1.申请空间 "<<endl;cout<<" 2.撤消作业 "<<endl;cout<<" 3.显示空闲表和分配表"<<endl;cout<<" 0.退出"<<endl;cout<<"请选择:";cin>>chioce;switch(chioce){case 1:assign();break;case 2:cancel();break;case 3:show();break;case 0:flag=0;break;default:cout<<"选择错误!"<<endl;}}}实验结果显示:【实验小结】本实验难度在两个方面,一是首次最佳适应算法assign(),这里我用的是结构体数组来存储空闲分区;二是对已分配分区的释放,这里同样采取结构体数组来存储已分配分区,用cancle()函数来实现。
采用首次适应算法的动态分区分配模拟课程设计实验报告
1 需求分析1)本程序要求实现对内存的动态分配与回收的模拟,同时,在内存的分配时还必须使用首次适应算法,最后,还要显示内存块分配和回收后空闲内存分区链的情况。
2)要实现对作业的内存分配,首先要有一个对作业进行创建和分配内存的模块,其中,该模块在分配内存时要使用首次适应算法;要实现对内存的回收,要有一个内存回收的模块,其中,该模块在回收内存时要考虑内存回收的四种情况;最后,还要有一个能显示内存空闲分区链的情况的模块。
2 概要设计1)首次适应算法的结构如图1:图1 首次适应算法的结构图2)数据结构:struct Fq{int size,o,no;Fq *before,*next;};其中,Fq表示结构体的名字(类型),size表示分区的可用空间大小,o表示该分区的状态(是否已分配),no表示该分区中的作业标志,*before表示该结点的向前指针,*next表示该结点的向后指针。
3)各种函数说明:void alloc(int b,int no,Fq *p);对作业no进行内存分配的功能函数;其中,参数b表示需求的内存大小,参数no表示作业的编号,参数*p表示空闲分区链的第一个非空结点的指针;void free(Fq *c);将地址为c的分区的内存回收;其中,参数*c表示要回收内存的结点;void create(Fq *head);创建新作业的子函数;其中,参数*head表示空闲分区链的链首指针;要配合函数alloc()使用;void cha(Fq *head);查看内存中的空闲分区链的子函数;其中,参数*head表示空闲分区链的链首指针;void hui(Fq *head);回收内存的子函数;其中,参数*head表示空闲分区链的链首指针;要配合函数free()使用;3 运行环境1)操作系统: Windows XP ( 32位 / DirectX 11 )2)电脑: X86 兼容台式电脑处理器: 英特尔 Pentium(奔腾) 双核 E5300 @ 2.60GHz内存: 2 GB4 开发工具和编程语言1)开发工具:Visual C++ 6.0;2)编程语言:C++语言;5 详细设计1)程序结构如图2:图2 程序结构图2)●主菜单模块:void main()//主函数{Fq *head=new Fq;head->next=new Fq;head->next->size=MAXSIZE;head->next->o=0;head->next->next=NULL;int choice=0;do{cout<<"请选择你要进行的操作:"<<endl;cout<<"1、创建新作业 2、查看空闲分区链 3、回收内存空间 0、退出"<<endl;cin>>choice;switch(choice){case 1: create(head);break;case 2: cha(head);break;case 3: hui(head);break;case 0: break;default: cout<<"输入错误!"<<endl;}}while(choice!=0);}●创建新作业模块:void create(Fq *head)//创建作业子函数{Fq *p=head->next;p->before=head;int no=0,b=0;cout<<"请输入要创建的作业的编号:";cin>>no;cout<<"请输入作业的需求空间大小:";cin>>b;alloc(b,no,p);//此处调用功能函数alloc()}●查看空闲分区链模块:void cha(Fq *head)//查看内存中的空闲分区链的子函数{Fq *p=head->next;p->before=head;int i=0;cout<<"空闲分区链的情况为:"<<endl;while(p!=NULL){if(p->o==0){cout<<"空闲分区"<<++i<<" "<<p->size<<"K"<<endl;}p=p->next;}}●回收内存空间模块:void hui(Fq *head)//回收内存的子函数{Fq *p=head->next;p->before=head;int no=0;cout<<"请输入要回收内存的作业号:";cin>>no;while(p!=NULL){if(p->no==no){free(p);//此处调用功能函数free()cout<<"作业"<<no<<"的内存已回收!"<<endl;return ;}else p=p->next;}}●内存分配功能函数模块:void alloc(int b,int no,Fq *p)//对作业no进行内存分配的子函数{while(p!=NULL){if(p->o==1) {p=p->next;}else{if(p->size>b){if(p->size-b<=min_size){p->o=1;p->no=no;}else{Fq *q=new Fq;Fq *r;r=p->before;r->next=q;q->before=r;q->next=p;p->before=q;q->size=b;p->size=p->size-b;q->no=no;q->o=1;}cout<<"内存分配成功!"<<endl;return ;}else p=p->next;}}cout<<"内存分配失败!"<<endl;}●内存回收功能函数模块:void free(Fq *c)//将地址为c的分区内存回收{if(c->before->o==0&&c->next->o==0){Fq *r=c->before,*s=c->next->next;r->size=(r->size+c->size+c->next->size);r->next=s;if(s!=NULL) s->before=r;}if(c->before->o==0&&c->next->o!=0){c->before->size=c->before->size+c->size;c->before->next=c->next;c->next->before=c->before;}if(c->next->o==0&&c->before->o!=0){Fq *r=c->next->next;c->size=c->size+c->next->size;c->next=c->next->next;if(r!=NULL) r->before=c;c->o=0;}else c->o=0;}6 调试分析1)内存分配功能函数模块:刚开始对作业分配内存时,只是将空闲分区的大小以及前后向指针进行修改,而没有对分配给作业的内存进行设置;这样,尽管内存的空闲分区大小已经变小,但是,以后却无法对已分配的内存空间以及作业进行修改;于是,我经过思考后,决定将分配给作业的内存空间也设置为一个分区,只不过不是空闲的分区,通过状态标识符o来与空闲分区进行区别。
操作系统实验报告三存储器管理实验
操作系统实验报告三存储器管理实验操作系统实验报告三:存储器管理实验一、实验目的本次存储器管理实验的主要目的是深入理解操作系统中存储器管理的基本原理和方法,通过实际操作和观察,掌握内存分配与回收的算法,以及页面置换算法的工作过程和性能特点,从而提高对操作系统资源管理的认识和实践能力。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C++,开发工具为 Visual Studio 2019。
三、实验内容1、内存分配与回收算法实现首次适应算法(First Fit)最佳适应算法(Best Fit)最坏适应算法(Worst Fit)2、页面置换算法模拟先进先出页面置换算法(FIFO)最近最久未使用页面置换算法(LRU)时钟页面置换算法(Clock)四、实验原理1、内存分配与回收算法首次适应算法:从内存的起始位置开始,依次查找空闲分区,将第一个能够满足需求的空闲分区分配给进程。
最佳适应算法:在所有空闲分区中,选择能够满足需求且大小最小的空闲分区进行分配。
最坏适应算法:选择空闲分区中最大的分区进行分配。
2、页面置换算法先进先出页面置换算法:选择最早进入内存的页面进行置换。
最近最久未使用页面置换算法:选择最近最长时间未被访问的页面进行置换。
时钟页面置换算法:给每个页面设置一个访问位,在页面置换时,从指针指向的页面开始扫描,选择第一个访问位为0 的页面进行置换。
五、实验步骤1、内存分配与回收算法实现定义内存分区结构体,包括分区起始地址、大小、是否已分配等信息。
实现首次适应算法、最佳适应算法和最坏适应算法的函数。
编写测试程序,创建多个进程,并使用不同的算法为其分配内存,观察内存分配情况和空闲分区的变化。
2、页面置换算法模拟定义页面结构体,包括页面号、访问位等信息。
实现先进先出页面置换算法、最近最久未使用页面置换算法和时钟页面置换算法的函数。
编写测试程序,模拟页面的调入和调出过程,计算不同算法下的缺页率,比较算法的性能。
首次适应算法 实验报告
首次适应算法实验报告引言首次适应算法(First Fit)是一种内存分配算法,用于解决操作系统中的内存管理问题。
在该算法中,操作系统将可用的内存空间分为若干个大小不等的分区,当一个新的作业需要分配内存时,算法通过在空闲分区列表中查找第一个能够满足作业大小的分区,找到第一个合适的位置将作业分配到该分区。
本次实验旨在通过调试和运行一个模拟的内存管理系统,了解首次适应算法的实现原理,并比较它与其他内存分配算法的性能差异。
实验环境- 操作系统:Windows 10- 开发语言:C++实验步骤和结果分析1. 设计数据结构我们首先设计了一个表示内存分区的数据结构`Partition`,包括以下成员变量:- `start`:表示分区的起始地址- `size`:表示分区的大小- `allocated`:表示分区是否已经分配给作业然后,我们设计了一个表示内存管理系统的数据结构`Memory`,包括以下成员变量:- `partitions`:表示分区列表,使用一个动态数组存储所有分区- `size`:表示内存总大小2. 实现首次适应算法在内存管理系统的实现中,我们通过设计一个`allocate`方法来实现首次适应算法的分配过程。
该方法接受一个作业的大小作为参数,返回一个指向分配的分区的指针。
如果找不到合适的分区,则返回`nullptr`。
首次适应算法的实现原理如下:- 遍历所有的分区,查找第一个未分配且大小大于作业大小的分区。
- 如果找到合适的分区,则将分区的`allocated`属性设置为`true`,表示已分配,并返回该分区的指针。
- 如果没有找到合适的分区,则返回`nullptr`。
3. 测试并分析结果在测试阶段,我们通过运行一系列的分配和释放操作来模拟作业的动态运行过程。
为了更好地观察内存的分配情况,我们将内存分为等大小的分区,并以图表的方式显示。
通过对不同大小的作业进行分配和释放测试,我们得到了如下结果:![内存分配示意图](memory_allocation.png)从上图可以看出,首次适应算法根据作业的大小选择不同的分区进行分配,确保了尽可能多地利用内存空间。
首次适应与循环首次适应算法实现
⾸次适应与循环⾸次适应算法实现⼀、实验内容编程实现⾸次适应与循环⾸次适应算法。
⼆、实验要求1.任选⼀种⾼级语⾔实现;三、实验过程1、 设计思想⾸次适应算法(FF):将所有空闲分区按照地址递增的次序链接,在申请内存分配时,从链⾸开始查找,将满⾜需求的第⼀个空闲分区分配给作业。
循环⾸次适应算法(NF):将所有空闲分区按照地址递增的次序链接,在申请内存分配时,总是从上次找到的空闲分区的下⼀个空闲分区开始查找,将满⾜需求的第⼀个空闲分区分配给作业2、 数据结构public class FreeArea {private int address;//内存地址private int size;//空闲区⼤⼩public FreeArea() {}public FreeArea(int address, int size) {this.address = address;this.size = size;}public int getAddress() {return address;}public void setAddress(int address) {this.address = address;}public int getSize() {return size;}public void setSize(int size) {this.size = size;}}4、运⾏结果:四、实验代码RR.Hpackage com.hu;import java.util.Scanner;public class MemoAlloc {public static void main(String[] args) {System.out.println("======⾸次适应算法======");FreeArea freeArea[]= init();FF(freeArea);System.out.println("=====循环⾸次适应算法=====");FreeArea freeArea1[]= init();NF(freeArea1);}public static void FF(FreeArea freeArea[]){//⾸次适应算法Scanner scanner = new Scanner(System.in);System.out.println("请输⼊要分配的内存⼤⼩:");int size = scanner.nextInt();for (int i =0;i<freeArea.length;i++){if (size<=freeArea[i].getSize()){//若分配内存⼤⼩⼩于空闲分区⼤⼩则分配成功System.out.println("分配内存成功");freeArea[i].setSize(freeArea[i].getSize()-size);//修改空闲分区⼤⼩break;}if (i== freeArea.length-1&&size>freeArea[i].getSize()) System.out.println("分配失败");}}public static void NF(FreeArea freeArea[]){//循环⾸次适应Scanner scanner = new Scanner(System.in);System.out.println("请输⼊要分配的内存⼤⼩:");int size = scanner.nextInt();boolean isWhile=true;int ProcessNum =0;int j=0;for (int i=ProcessNum;i< freeArea.length;i++,j++){if (size <= freeArea[i].getSize() ) {//若分配内存⼤⼩⼩于空闲分区⼤⼩则分配成功System.out.println("分配内存成功");freeArea[i].setSize(freeArea[i].getSize() - size);ProcessNum = j+1;//下⼀次查找时从本次找到的空闲分区的下⼀个分区开始找break;}else if (ProcessNum!=0 && i== freeArea.length-1&&size>freeArea[i].getSize()){ProcessNum=0;//若开始查找时不是从链⾸开始,最后⼀个空闲分区⼤⼩仍不能满⾜要求,则返回第⼀个空闲分区}else if(ProcessNum==0&&i== freeArea.length-1&&size>freeArea[i].getSize()){System.out.println("分配失败");//若开始查找时是从链⾸开始,最后⼀个空闲分区⼤⼩仍不能满⾜要求,则分配失败};}}public static FreeArea[] init(){//空闲区初始化并排序System.out.println("初始化空闲区并分配内存地址与⼤⼩");Scanner scanner = new Scanner(System.in);FreeArea[] freeAreas = new FreeArea[5];for (int i=0;i<freeAreas.length;i++){System.out.println("请输⼊内存地址与⼤⼩:");freeAreas[i] = new FreeArea(scanner.nextInt(),scanner.nextInt());}FreeArea t;for (int i = 0;i<freeAreas.length;i++){for (int j = 0;j<freeAreas.length-1;j++){if(freeAreas[j].getAddress()>freeAreas[j+1].getAddress()){t = freeAreas[j+1];freeAreas[j+1]=freeAreas[j];freeAreas[j]=t;}}}return freeAreas;}}五、实验总结通过本次实验我更加了解了循环⾸次适应与⾸次适应算法,⾸次适应算法优先利⽤低地址部分空闲分区,保留了⾼地址部分的⼤空闲区,缺点是低址部分不断被划分,会留下很多难以利⽤的⼩的外部碎⽚,每次都从低地址部分开始查会增加查找时的开销。
首次适应算法
计算机操作系统实验一、实验名称:首次适应算法二、实验目的:熟悉并利用首次适应算法进行分配内存资源和回收资源。
三、设计思想:从空闲分区表的第一个表目起查找该表,把最先能够满足要求的空闲区分配给作业,这种方法目的在于减少查找时间。
为适应这种算法,空闲分区表(空闲区链)中的空闲分区要按地址由低到高进行排序。
该算法优先使用低址部分空闲区,在低址空间造成许多小的空闲区,在高地址空间保留大的空闲区。
流程图(1)分配内存流程图(2)释放内存①当前作业为内存中最后一个作业②当前作业为倒数第二个作业③当前作业在链表中间四、主要数据结构:typedef struct memory{struct memory *former; //前向指针int waddress;//地址int wnum;//作业号int size;//分配内存大小int type;//状态0表示空闲1表示已分配struct memory *next; //后向指针}MEMORY;MEMORY *mem;五、运行结果截图分配内存释放内存附录1#include <iostream>#include <stdlib.h>#include <stdio.h>typedef struct memory{struct memory *former; //前向指针int waddress;//地址int wnum;//作业号int size;//分配内存大小int type;//状态0表示空闲1表示已分配struct memory *next; //后向指针}MEMORY;MEMORY *mem;void prfmem(MEMORY *ptr) //打印显示内存情况{MEMORY *temp;temp=ptr->next;printf("内存链的状态为:\n");while(temp!=NULL){if(temp->type==0){printf("内存空闲\n起始地址为:%d 空闲空间大小为:%d\n",temp->waddress,temp->size);}else{printf("内存已分配\n起始地址为%d 分配空间大小为%d 运行的作业号%d\n",temp->waddress,temp->size,temp->wnum);}temp=temp->next;}}void allocwork(MEMORY *ptr,MEMORY *assign)//根据算法分配内存{int sizemin;if(ptr->next==NULL)//内存没有作业运行{if(ptr->size>=assign->size){ptr->size=ptr->size-assign->size;assign->type=1;ptr->next=assign;assign->former=ptr;printf("作业%d申请%d的内存空间\n",assign->wnum,assign->size);}else{printf("没有足够的内存空间为作业%d分配\n",assign->wnum);delete assign;}}else //内存中如果已经分配了空间{MEMORY *previous,*current;previous=ptr;current=previous->next;while(current!=NULL){if(current->size>=assign->size&¤t->type==0){break;}previous=current;current=current->next;}if(current==NULL)//空闲链中没有为作业分配所需的空间,即释放的空闲区间小于要分配的作业空间{if(ptr->size>=assign->size){assign->waddress =640-(ptr->size);ptr->size=ptr->size-assign->size;assign->type=1;assign->former=previous;previous->next=assign;printf("作业%d申请%d的内存空间\n",assign->wnum,assign->size);}elseprintf("没有足够的内存空间为作业%d分配\n",assign->wnum);}else //释放的空闲链中有可为此作业分配的空间{if((current->size-assign->size)<=sizemin)//空闲链所具备的空间与作业所需空间大小差不多时{current->wnum=assign->wnum;current->type=1;delete assign;printf("作业%d申请%d的内存空间\n",assign->wnum,assign->size);}else{current->size=current->size-assign->size;assign->type=1;assign->waddress=current->waddress+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;}printf("作业%d申请%d的内存空间\n",assign->wnum,assign->size);}}}}void FF(int i)//依次初始化作业,对作业分配内存{int work[6];MEMORY *running;running=(MEMORY *)malloc(sizeof(MEMORY));printf("输入作业大小:\n");scanf("%d",&work[i]);if(running!=NULL){ running->former=NULL;running->waddress=0;running->wnum=i;running->size=work[i];running->type=0;running->next=NULL;allocwork(mem,running); prfmem(mem);}elseprintf("没有足够的内存空间\n");}void releasemem(MEMORY *ptr,int i)//释放内存{MEMORY *previous,*current;previous=ptr; current=previous->next;while(current!=NULL) //找到需要释放的作业位置{if(current->type==1&¤t->wnum==i){ break;}previous=current;current=current->next;}if(current==NULL){ printf("内存中没有找到需要释放的作业!\n"); return; }else if(current->next==NULL) //当前作业为内存中最后一个作业{if(previous->type==0) //与前一个相邻空闲区合并{previous->size=previous->size+current->size;previous->next=NULL;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else{current->type=0;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}}else if((current->next)->next==NULL)//当前作业为倒数第二个作业{if(previous->type==0&&(current->next)->type==0) //释放的地址空间前后均为空闲区{previous->size=previous->size+current->size+(current->next)->size;previous->next=NULL;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else if(previous->type==0) //前面有空闲块{previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else if((current->next)->type==0)//后面有空闲块{current->size=current->size+(current->next)->size;current->type=0;current->next=NULL;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else //前后都没有空闲块{current->type=0;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}}else //当前作业在链表中间{if(previous->type==0&&(current->next)->type==0) //前后均为空闲区{previous->size=previous->size+current->size+(current->next)->size;((current->next)->next)->former=previous;previous->next=(current->next)->next;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else if(previous->type==0) //前面有空闲块则把它和前面的合并{previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else if((current->next)->type==0) //释放的地址空间后面有空闲块{current->size=current->size+(current->next)->size;current->type=0;((current->next)->next)->former=current;current->next=(current->next)->next;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}else //前后都没有空闲块{current->type=0;printf("作业%d释放%d的空间\n",current->wnum,current->size);prfmem(mem);}}}void initmem() //初始化{int a,i,j;mem=new MEMORY;mem->size=640;mem->former=0;mem->next=0;printf("申请内存请输入1\n"); printf("释放内存请输入2\n");scanf("%d",&a);while(a==1||a==2){if(a==1){printf("输入申请内存的作业编号1-5\n");scanf("%d",&i);FF(i);}if(a==2){printf("输入释放内存的作业编号1-5\n");scanf("%d",&j);releasemem(mem,j);}printf("申请内存请输入1\n"); printf("释放内存请输入2\n"); printf("退出输入其他键\n");scanf("%d",&a);}}void main(){initmem();}。
首次适应算法和循环首次适应算法
首次适应算法和循环首次适应算法一、实验目的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();六、实验总结在一开始老师布置这次的实验题目时,自己根本不知道要干什么,因为在上课时对动态分区分配这节内容不是太了解,所以在上机时不知道如何下手,后来,将本章内容反复的看了几遍之后,终于有了自己的思路。
可分区管理实验报告
一、实验目的1. 理解可分区管理的基本原理和方法。
2. 掌握可变分区分配算法(首次适应算法、循环首次适应算法、最佳适应算法)的原理和实现。
3. 通过实验,加深对存储管理方案的理解,提高编程能力。
二、实验环境1. 操作系统:Windows 102. 编程语言:C/C++3. 开发工具:Visual Studio三、实验原理可分区管理是一种常见的存储管理方法,它将物理内存划分为若干个大小可变的区域,每个区域称为一个分区。
系统在分配内存时,根据进程的需求从分区中选择一个合适的分区进行分配。
可分区管理主要分为以下三种算法:1. 首次适应算法:按照分区表的顺序,从第一个分区开始查找,找到第一个满足需求的分区进行分配。
2. 循环首次适应算法:与首次适应算法类似,但每次查找都是从上次查找的下一个分区开始,直到找到合适的分区为止。
3. 最佳适应算法:在整个内存中寻找一个大小最接近需求且能满足需求的分区进行分配。
四、实验步骤1. 定义分区表结构体,包含分区起始地址、分区大小、分区状态等信息。
2. 实现可变分区分配函数,根据选择的分配算法进行内存分配。
3. 实现内存回收函数,将释放的分区状态设置为空闲。
4. 编写主函数,模拟进程的创建、分配和回收过程。
五、实验代码```c#include <stdio.h>#include <stdlib.h>#define MAX_PARTITIONS 100typedef struct {int startAddress;int size;int state; // 0: 空闲,1: 已分配} Partition;Partition partitions[MAX_PARTITIONS];int partitionCount = 0;void initializePartition() {for (int i = 0; i < MAX_PARTITIONS; i++) {partitions[i].startAddress = 0;partitions[i].size = 0;partitions[i].state = 0;}partitionCount = 0;}int allocateMemory(int size, int algorithm) {for (int i = 0; i < partitionCount; i++) {if (partitions[i].state == 0 && partitions[i].size >= size) { switch (algorithm) {case 1: // 首次适应算法partitions[i].state = 1;return partitions[i].startAddress;case 2: // 循环首次适应算法if (i == partitionCount - 1) {i = 0;}break;case 3: // 最佳适应算法if (i == partitionCount - 1) {i = 0;}break;}}}return -1; // 分配失败}void freeMemory(int startAddress) {for (int i = 0; i < partitionCount; i++) {if (partitions[i].startAddress == startAddress) { partitions[i].state = 0;return;}}}int main() {initializePartition();// 创建进程并分配内存int process1 = allocateMemory(100, 1);printf("Process 1 allocated at %d\n", process1);int process2 = allocateMemory(200, 2);printf("Process 2 allocated at %d\n", process2);int process3 = allocateMemory(300, 3);printf("Process 3 allocated at %d\n", process3);// 回收内存freeMemory(process1);printf("Process 1 memory freed\n");int process4 = allocateMemory(150, 1);printf("Process 4 allocated at %d\n", process4);return 0;}```六、实验结果与分析通过实验,我们可以观察到以下结果:1. 当采用首次适应算法时,内存分配的速度较快,但可能导致内存碎片化。
首次适应算法最佳适应算法
spare *s;
s=(spare *) malloc(count*sizeof(spare));
init(s,count);
cout<<"首次适应算法:"<<endl;
FF(s,count);
cout<<"最佳适应算法"<<endl;
sort(s,count);
FF(s,count);
姓名:
学号:
实验名称:进程调度模拟实验
实验目的:了解动态分区存储管理方式中的数据结构和分配算法,加深对动态分区存储管理方式及其实现技术的理解。
实验内容:
#include<iostream.h>
#include <malloc.h>
typedef struct Spare
{
int SA;
int size;
{
spare min;
for(int i=0;i<count;i++)
for(int j=i;j<count;j++)
if(s[j].SA <s[i].SA )
{
min=s[j];
s[j]=s[i];
s[i]=min;
}
}
void FF(spare *s,int count)
{
int i=1,Jsize,j=0;
char c='Y';
cout<<"请输入您想分配的作业"<<endl;
while(c=='Y' )
{
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作操作系统大作业题目:首次适应算法分配内存学号:1207300142学生姓名:张鲁云班级:计科121首次适应算法分配内存一、问题描述在内存分配中,动态分区是根据实际的进程需求,动态地为之分配空间。
而首次适应算法分配时从表头指针开始查找可利用空间表,将找到的第一个大小不小于“请求”的空闲块的一部分分配给用户。
可利用空间表本身既不按节点的初始地址有序,也不按节点的大小有序。
用户释放内存,回收时只是将空闲块插入在链表的表头即可,此算法比较节省时间。
二、运行环境VC6.0三、算法思想。
首次适应算法要求空闲分区链以地址递增的次序链接。
在分配内存时,从链首开始查找,直到找到一个大小能满足要求的空闲分区为止;然后按照作业大小,从该分区中划出一块内存空间分配给请求者,余下的空闲区仍留在空闲链中。
若从链首到链尾都不能找到一个能满足要求的分区,则此次分配失败。
四、实验目的在计算机系统中,为了提高内存区的利用率,必须给电脑内存区进行合理的分配。
本实验通过对内存区分配方法首次适应算法的使用,来了解内存分配的模式。
五、首次适应算法分配内存算法概要(1)结构体Typedef struct freearea//定义一个空闲区说明表结构{ long size; //分区大小long address; //分区地址int state; //状态}ElemType; // 线性表的双向链表存储结构Typedef struct DuLNode{ ElemType data;structDuLNode *prior; //前趋指针structDuLNode *next; //后继指针} DuLNode,*DuLinkList;Status Initblock(intMAX_length)//开创带头结点的内存空间链表{ 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; //尾结点的地址是0block_last->data.size=MAX_length; //分区大小是最大分区block_last->data.state=Free; //状态是空return OK; }(2)主要函数说明:void alloc();进行内存分配的功能函数。
Status free(int flag)将地址为flag的分区的内存回收。
Status First_fit(int request)创建进程空间的子函数;其中,参数request表示空闲分区链的链首指针;要配合函数alloc()使用。
void show()查看内存中的分区情况。
七、代码实现#include<iostream.h>#include<stdlib.h>#include<stdio.h>#define Free 0 //空闲状态#define Busy 1 //已用状态#define OK 1 //完成#define ERROR 0 //出错//#define MAX_length 640 //最大内存空间为640KB typedefint Status;int flag;typedefstructfreearea//定义一个空闲区说明表结构{long size; //分区大小long address; //分区地址int state; //状态}ElemType; // 线性表的双向链表存储结构typedefstructDuLNode{ElemType data;structDuLNode *prior; //前趋指针structDuLNode *next; //后继指针} DuLNode,*DuLinkList;DuLinkListblock_first; //头结点DuLinkListblock_last; //尾结点Status alloc(int);//内存分配Status free(int); //内存回收Status First_fit(int);//首次适应算法void show();//查看分配Status Initblock();//开创空间表Status Initblock(intMAX_length)//开创带头结点的内存空间链表{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; //尾结点的地址是0block_last->data.size=MAX_length; //分区大小是最大分区block_last->data.state=Free; //状态是空return OK;}//分配主存Status alloc() {int request = 0;printf("请输入需要分配的主存大小(单位:KB):");scanf("%d",&request);if(request<0 ||request==0){printf("配大小不合适,请重试!");return ERROR;}{if(First_fit(request)==OK)printf("分配成功!");elseprintf("内存不足,分配失败!");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 free(int flag) {DuLNode *p=block_first;for(inti= 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;printf("主存分配情况:\n");DuLNode *p=block_first->next;printf("分区号\t起始地址\t分区大小\t状态\n\n");while(p){printf("%d ",flag);flag++;printf("%d \t",p->data.address);printf("%dKB \t",p->data.size);if(p->data.state==Free)printf("空闲\n\n");elseprintf("已分配\n\n");p=p->next;}printf("++++++++++++++++++++++++++++++++++++++++++++++\n\n");}//主函数void main(){int c=1;intMAX_length;//算法选择标记printf("首次适应算法内存分配算法:\n");printf("input MAX_length:\n");scanf("%d",&MAX_length);Initblock(MAX_length); //开创空间表int choice;//操作选择标记while(c=1){show();printf("请输入您的操作:");printf("\n1: 分配内存\n2: 回收内存\n0: 退出\n");scanf("%d",&choice);{if(choice==1){alloc(); // 分配内存c=1;}else if(choice==2) // 内存回收{int flag;printf("请输入您要释放的分区号:\n");scanf("%d",&flag);free(flag);c=1;}else if(choice==0){break; //退出}else //输入操作有误{printf("输入有误,请重试!\n");c=1;}}printf("&&&&&&&\n");}}八、运行截图九、思考这次试验模拟内存分配,模拟了操作系统是如何通过作业调度选择作业进入内存以及系统是如何为进入内存的作业分配内存空间,实现多道作业同时驻留内存,就绪进程队列中的多个进程是如何以分式方式共享CPU,作业运行完成离开系统时,系统如何进行内存回收,采用的是首次适应算法,应用的数据结构是双向链表。