1、实验报告【实验名称】 首次适应算法和循环首次适应算法 【实验目的】理解在连续分区动态的存储管理方式下,如何实现主存空间的分配与回收。【实验原理】首次适应(first fit,FF)算法FF 算法要求空闲分区链以地址递增的次序链接。在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区即可。然后再按照作业的大小,从该分区中划出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。若从链首直至链尾都不能找到一个能满足要求的分区,则表明系统中已经没有足够大的内存分配给该进程,内存分配失败,返回。循环首次适应(next fit ,NF)算法为避免低址部分留下许多很小的空闲分区,以及
2、减少查找可用空闲分区的开销,循环首次适应算法在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块玉请求大小相等的内存空间分配给作业。【实验内容】实现主存空间的分配与回收:1. 采用可变式分区管理,使用首次适应算法实现主存空间的分配与回收;2. 采用可变式分区管理,使用循环首次适应算法实现主存空间的分配与回收。数据结构和符号说明:typedef struct PCB/进程控制块char ProgressName10; /进程名称int Startaddress; /进程开始地址int Progress
3、Size; /进程大小int ProgressState = 0; /进程状态;typedef struct FREE /空闲区结构体int Free_num; /空闲区名称int Startaddress; /空闲区开始地址int Endaddress; /空闲区结束地址int Free_Space; /空闲区大小;算法流程图:首次适应算法开始空闲区登记插入作业空闲区指针指向第一个空闲区当前空闲区是否满足要求 ?插入作业 , 修改内存信息和作业信息表是是否继续插入 ?结束否是否为最后一个空闲区 ?否插入失败是空闲区指针指向下一个空闲区否是循环首次适应算法开始作业插入失败空闲区登记插入作业空闲
4、区指针指向第一个空闲区 ,标记当前空闲区P当前空闲区是否满足插入当前作业 , 修改内存信息和作业信息表信息结束继续插入 ?空闲区指针指向下一个空闲区 , 标记当前空闲区 P空闲区指针加一是否为最后一个空闲区空闲区指针指向第一个空闲区当前空闲区是否满足是否小于所标记的空闲区 P当前指针所指向区域是否满足空闲区指针指向下一个空闲区是否否是否是否是否是输出信息否是程序代码及截图:#include#include#include #include #define N 1024typedef struct PCB/进程控制块char ProgressName10; /进程名称int Startaddre
5、ss; /进程开始地址int ProgressSize; /进程大小int ProgressState = 0; /进程状态;typedef struct FREE /空闲区结构体int Free_num; /空闲区名称int Startaddress; /空闲区开始地址int Endaddress; /空闲区结束地址int Free_Space; /空闲区大小;int count = 0; /当前内存中进程个数bool ROMN;/设置内存块int p = 0;/循环首次使用需要标记当前的空闲区块FREE FREE100;/设置空闲区数组为 100 个int FREE_counter = 0
6、;/空闲区的个数PCB num20; /作业队列void init()/初始化操作for(int i=0; inumj+1.Startaddress)a = numj;numj = numj+1;numj+1 = a;for(int i=0; icount; i+)if(numi.ProgressState!=0)printf(“%stt%dttt%dtt%dttn“,numi.ProgressName,numi.Startaddress,numi.ProgressSize,numi.ProgressSize+numi.Startaddress-1);printf(“-n“);void sho
7、wFree()/打印空闲区的情况printf(“-n“);printf(“ 空闲区名t| 开始地址t| 大小 t| 结束地址n“);printf(“-n“);for (int i=1; i= FREE_counter; i+)printf(“t%1dt%8dt%11dt %dn“,FREEi.Free_num,FREEi.Startaddress, FREEi.Free_Space,FREEi.Endaddress);printf(“-n“);void find_FREE() /寻找空闲区int i,j,p; /计数值FREE_counter = 0;/预设空闲区数为 0for(i = 0;
8、i N; i+)if(ROMi = 0)p = i;for(j = i; j N; j+)if(ROMj=0)/未找到空闲区,则将 j 赋值给 i 后继续循环i = j;continue;if(ROMj=1)/找到空闲区FREE_counter+;/空闲区个数+1;FREEFREE_counter.Free_num = FREE_counter;/设置空闲区编号FREEFREE_counter.Startaddress = p;FREEFREE_counter.Endaddress = j-1;FREEFREE_counter.Free_Space = j-p;i=j+1;break;if(j
9、 = N FREE FREE_counter.Free_num = FREE_counter;/对空闲区进行处理FREE FREE_counter.Startaddress = p;FREE FREE_counter.Endaddress =j-1;FREE FREE_counter.Free_Space = j-p;void First_Fit(PCB for(i=0; iN; i+)if(ROMi=0)for(j=i; j=(i+a.ProgressSize) j+)/查询第一个空闲区,并判断是否适合插入作业if(ROMj=1)i = j + 1;break;if(j=i+a.Progre
10、ssSize+1)a.Startaddress = i;/设置作业的开始地址a.ProgressState = 1;/标记作业在内存中for(k=i; ki+a.ProgressSize k+)ROMk=1;printf(“进程%s 插入成功,进程%s 的初始地址为%d,结束地址为%dn“,a.ProgressName,a.ProgressName,a.Startaddress,a.Startaddress+a.ProgressSize-1);return;if(i=N)/未查询到合适的区域printf(“插入失败,无可用空间!n“);void Next_Fit(PCB for(i=p; iN
11、; i+)/从所标记的当前区域开始查询,查询到末内存if(ROMi=0)for(j=i; j=(i+a.ProgressSize) j+)if(ROMj=1)i = j+1;break;if(j=i+a.ProgressSize+1)/找到合适的空闲区a.Startaddress=i;a.ProgressState=1;for(k=i; ki+a.ProgressSize k+)ROMk=1;printf(“插入成功,进程%s 的初始地址为%d,结束地址为%dn“,a.ProgressName,a.Startaddress,a.Startaddress+a.ProgressSize-1);p=
12、i+a.ProgressSize;return;for(i=0; ip; i+)/当未找到时,从第一个空闲区开始查询,结束条件为小于所标记的 Pif(ROMi=0)for(j=i; j=(i+a.ProgressSize) j+)if(ROMj=1)i=j+1;break;if(j=i+a.ProgressSize+1)/成功找到结束,并标记当前 P 为现在的作业的尾部a.Startaddress=i;a.ProgressState=1;for(k=i; ki+a.ProgressSize k+)ROMk=1;printf(“插入成功,进程%s 的初始地址为%dn“,a.ProgressNam
13、e,a.Startaddress);p=i+a.ProgressSize;break;if(i=p)/查询两部分都未找到合适的区域,输出插入失败语句printf(“插入失败,无可用空间n“);void Delete(PCB for(i=a.Startaddress; ia.Startaddress+a.ProgressSize; i+)ROMi=0;a.ProgressState=0;/状态标记为未使用printf(“进程%s 删除成功n“,a.ProgressName);int main()int choose1,choose;char ProgressName10;PCB a;init()
14、;printf(“t 主存空间的分配与回收n“);printf(“-n“);printf(“t1、首次适应算法n“);printf(“t2、循环首次适应算法n“);printf(“-n“);printf(“请选择分配算法:“);scanf(“%d“,system(“cls“);while(1)w:system(“cls“);printf(“当前分配算法:“);if(choose1 = 1)printf(“首次适应算法n“);elseprintf(“循环首次适应算法n“);printf(“-n“);printf(“t1、插入进程n“);printf(“t2、删除进程n“);printf(“t3、
15、显示进程的信息n“);printf(“t4、显示空闲区n“);printf(“-n“);printf(“请输入:“);scanf(“%d“,system(“cls“);switch(choose)case 1:printf(“请输入进程名:“);scanf(“%s“,printf(“请输入进程的大小:“);scanf(“%d“,for(int i = 0; i count; i+)if(strcmp(numi.ProgressName,a.ProgressName)=0)printf(“已存在同名进程,无法插入。n“);system(“pause“);goto w;if(choose1=1)/
16、首次适应算法First_Fit(a);elseNext_Fit(a);/循环首次适应算法numcount+=a;break;case 2:if(count = 0)printf(“当前没有进程在内存中,无法删除!n“);system(“pause“);goto w;printf(“输入删除的进程名字:“);scanf(“%s“,for(int i=0; icount; i+)if(!strcmp(numi.ProgressName,ProgressName)Delete(numi);elseprintf(“没有找到对应进程,请重新输入。n“);break;case 3:showProgress(a);break;case 4:find_FREE();showFree();break;default:printf(“n 无效的输入。n“);system(“pause“);return 0;主界面:首次适应算法,初始空闲区:插入进程:插入 3 个进程:空闲区信息:删除进程 2:删除后空闲区状况:再插入一个进程,可以看到其其初始地址为 100:循环首次适应算法,插入 3 个进程删除进程 2 后:再插入进程 A,发现其从上次找到的空闲分区的下一个空闲分区开始查找,其初始地址为 750 而不是 200: