主存空间的分配与回收—首次适应法

合集下载

实验报告二主存空间的分配和回收

实验报告二主存空间的分配和回收
temp=freeTab; /*寻找空闲表中对应登记项*/
if(strcmp(PName,"OS")==0)
{ printf("ERROR!");
return;
}
while((strcmp(temp->proID,PName)!=0||temp->flag==1)&&temp)
temp=temp->next;
四、程序中使用的数据结构及符号说明
结构1:
typedef struct freeTable
{
char proID[6];
int startAddr; /*空闲区起始地址*/
int length; /*空闲区长度,单位为字节*/
int flag; /*空闲区表登记栏标志,用"0"表示空表项,用"1"表示未分配*/
freeNode=freeNode->next;
}
getchar();
break;
default:printf("没有该选项\n");
}/*case*/
}/*while*/
}/*main()*/
六、运行调试结果
初始界面:
分配主存,五个作业名:P1、P2、P3、P4、P5
显示主存使用情况:
回收主存P2:
if(front->flag==1&&rear->flag==1)
/* 上邻空闲区,下邻空闲区,三项合并*/
{
front->length=front->length+rear->length+temp->length;

操作系统实验可变分区内存分配首次适应算法模拟

操作系统实验可变分区内存分配首次适应算法模拟

操作系统实验可变分区内存分配首次适应算法模拟(总6页)--本页仅作为文档封面,使用时请直接删除即可----内页可以根据需求调整合适字体及大小--题目可变分区内存分配首次适应算法模拟姓名:学号:专业:学院:指导教师:林夕二零一八年十一月一、实验目的主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。

二、实验内容及原理编写一个内存动态分区分配模拟程序,模拟内存的分配和回收的完整过程。

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

可变分区方式是按作业需要的主存空间大小来分割分区的。

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

随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。

当进程运行完毕释放内存,系统根据回收区的首址,从空闲区链表中找到相应的插入点,此时可能出现以下4种情况之一:1.回收区与插入点的前一个空闲分区F1相邻接,此时将两个分区合并2.回收区与插入点的后一个空闲分区F2相邻接,此时将两个分区合并3.回收区与插入点的前,后两个空闲分区相邻接,此时将三个分区合并4.回收区既不与F1相邻接,又不与F2相邻接,此时应为回收区单独建立一个新表项三、程序设计1.算法流程3.详细设计(1)定义两个结构体struct kongxian ength>=len) tart=kongxian[i].start;zuoye[n2].end=zuoye[n2].start+len;zuoye[n2].length=len;n2++; ength==len) tart=kongxian[j+1].start;kongxian[j].end=kongxian[j+1].end;kongxian[j].length=kongxian[j+1].length;}n1--;}else tart+=len;kongxian[i].length-=len;}}(3)回收作业:printf("输入要回收的作业ID ");scanf("%d",&id);front=middle=behind=0;for(i=0;i<n1;i++){if(kongxian[i].start>zuoye[id].end)break;if(kongxian[i].end==zuoye[id].start) tart==zuoye[id].end)tart-(*(struct kongxian *)b).start;}int cmp2(const void *a,const void *b){return (*(struct zuoye *)a).start-(*(struct zuoye *)b).start;}void init(){n1=1; tart=0;kongxian[0].end=1023;kongxian[0].length=1024;}void print1() tart,kongxian[i].end,kongxian[i].length);}void print2() tart,zuoye[i].end,zuoye[i].length);}int main(){int i,j,k,t,len,flag,id;int front,middle, behind;int t1,t2;init();print1();printf("输入1装入新作业,输入0回收作业,输入-1结束\n");while(scanf("%d",&t)!=EOF){if(t==1) ength>=len) tart=kongxian[i].start;zuoye[n2].end=zuoye[n2].start+len;zuoye[n2].length=len;n2++; ength==len) tart=kongxian[j+1].start;kongxian[j].end=kongxian[j+1].end;kongxian[j].length=kongxian[j+1].length;}n1--;}else tart+=len;kongxian[i].length-=len;}}}else if(t==0){printf("输入要回收的作业ID ");scanf("%d",&id);front=middle=behind=0;for(i=0;i<n1;i++){if(kongxian[i].start>zuoye[id].end)break;if(kongxian[i].end==zuoye[id].start)tart==zuoye[id].end) tart=zuoye[id].start;kongxian[n1].end=zuoye[id].end;kongxian[n1].length=zuoye[id].length;n1++; tart=zuoye[j+1].start;zuoye[j].end=zuoye[j+1].end;zuoye[j].length=zuoye[j+1].length;}n2--;}if(front &&behind) nd+=zuoye[id].length;kongxian[t1].length+=zuoye[id].length;for(j=id;j<n2-1;j++) tart=zuoye[j+1].start;zuoye[j].end=zuoye[j+1].end;zuoye[j].length=zuoye[j+1].length;}n2--;}if(middle) nd=kongxian[t2].end;kongxian[t1].length+=(zuoye[id].length+kongxian[t2].length);tart=kongxian[j+1].start;kongxian[j].end=kongxian[j+1].end;kongxian[j].length=kongxian[j+1].length;}n1--;for(j=id;j<n2-1;j++) tart=zuoye[j+1].start;zuoye[j].end=zuoye[j+1].end;zuoye[j].length=zuoye[j+1].length;}n2--;}if(behind &&!middle) tart-=zuoye[id].length;kongxian[t2].length+=zuoye[id].length;for(j=id;j<n2-1;j++) tart=zuoye[j+1].start;zuoye[j].end=zuoye[j+1].end;zuoye[j].length=zuoye[j+1].length;}n2--;}}else{printf("操作结束\n");break;}print1();print2();}return 0;}。

动态分区存储管理方式的主存分配回收总结

动态分区存储管理方式的主存分配回收总结

动态分区存储管理方式的主存分配回收总结动态分区存储管理是一种常见的主存分配回收技术,它通过动态创建并分配大小不等的存储块来管理主存空间,以满足不同进程的需求。

这种管理方式在操作系统中起着至关重要的作用,因此本文将对动态分区存储管理的主存分配回收进行总结,从原理、特点、优缺点及其在实际应用中的情况进行阐述。

一、原理动态分区存储管理是基于分区的主存管理机制,它将主存空间划分为多个不等大小的分区,每个分区可以被分配给一个进程使用。

当系统收到一个新进程的请求时,它会根据需要的主存大小为进程分配一个合适大小的分区。

当进程执行完毕,系统会回收该进程所占用的分区,使得该空间可以再次被分配给其他进程使用。

在动态分区存储管理中,主要有两种分配方式:首次适应算法和最佳适应算法。

首次适应算法是从第一个满足大小要求的分区开始进行分配;而最佳适应算法是从所有满足大小要求的分区中选择最小的分区进行分配。

这两种分配方式都有自己的优点和局限性,但它们都是基于动态分区存储管理的基本原理。

二、特点1.灵活性动态分区存储管理可以根据进程的需求动态地分配和回收主存空间,提高了主存的利用率和效率。

进程可以根据需要申请和释放主存空间,而无需预先分配固定大小的空间。

2.节省空间动态分区存储管理可以尽可能地利用主存中的碎片空间,减少了外部碎片的浪费。

这种管理方式能够充分利用主存空间,提高了主存的利用率。

3.多样性动态分区存储管理可以适应不同大小的进程需求,能够根据进程的大小灵活地进行分区分配,满足了不同进程的需求。

三、优缺点1.优点(1)提高了主存的利用率和效率。

(2)灵活地分配和回收主存空间,满足不同进程的需求。

(3)节省了主存空间,减少了碎片的浪费。

2.缺点(1)会产生外部碎片,影响了分区空间的利用率。

(2)分配和回收过程中可能产生较大的开销,影响了系统的性能。

四、在实际应用中的情况动态分区存储管理在操作系统中得到了广泛的应用,特别是在多道程序设计和实时系统中。

用首次适应算法模拟内存的分配和回收

用首次适应算法模拟内存的分配和回收

操作系统实验报告完成日期:2011-12-5用首次适应算法模拟内存的分配和回收一、实验目的在计算机系统中,为了提高内存区的利用率,必须给电脑内存区进行合理的分配。

本实验通过对内存区分配方法首次适应算法的使用,来了解内存分配的模式。

在熟练掌握计算机分区存储管理方式的原理的基础上,编程模拟实现操作系统的可变分区存储管理的功能,一方面加深对原理的理解,另一方面提高根据已有原理通过编程解决实际问题的能力,为进行系统软件开发和针对实际问题提出高效的软件解决方案打下基础。

二、实验内容与数据结构:(1)可变式分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需要,并且分区的个数是可以调整的。

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

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

有的分区被分配作业占用,有的分区空闲,例如,某时刻主存空间占用情况如图所示:为了说明哪些分区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,如下图所示。

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

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

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

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

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

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

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

作业的释放区与空闲区的邻接分以下4种情况考虑:A、释放区下邻空闲区;B、释放区上邻空闲区;C、释放区上下都与空闲区邻接;D、释放区上邻空闲区不邻接;二、实验要求1.内存大小初始化2.可以对内存区进行动态分配,采用首次适应算法来实现3.可以对已分配的内存块进行回收,并合并相邻的空闲内存块。

实验二存储器的分配与回收算法实现

实验二存储器的分配与回收算法实现

实验二存储器的分配与回收算法实现一、实验目的1.学习存储器的分配与回收算法;2.实现动态存储管理的相关算法。

二、实验原理在计算机系统中,存储器是一项重要的资源。

为了有效地利用存储器资源,需要设计合理的存储器管理算法来进行存储器的分配与回收。

常用的存储器管理算法有以下几种:1. 首次适应算法(First Fit):分配内存时从链表的头部开始查找第一个满足要求的空闲内存单元。

2. 最佳适应算法(Best Fit):分配内存时从整个链表中找到最小的满足要求的空闲内存单元。

3. 最坏适应算法(Worst Fit):分配内存时从整个链表中找到最大的满足要求的空闲内存单元。

4. 循环首次适应算法(Next Fit):分配内存时从上一次分配结束的位置开始查找第一个满足要求的空闲内存单元。

5. 最近最少使用策略(Least Recently Used, LRU):当内存不足时,将最近最久未使用的页面置换出去。

6.先进先出策略(FIFO):将最先进入缓冲区的页面置换出去。

三、实验步骤1.首先,我们需要定义一个数据结构来表示存储器块,该数据结构包含以下字段:-起始地址:表示该存储器块的起始地址;-大小:表示该存储器块的大小;-状态:表示该存储器块的使用状态(空闲/已分配);-下一存储器块地址:指向链表中下一个存储器块的地址。

2.然后,创建一个链表来表示存储器块的集合,链表的每个节点表示一个存储器块。

3. 实现首次适应算法(First Fit):-遍历链表,找到第一个大小大于等于所需内存的空闲存储器块;-将该存储器块标记为已分配,并更新链表中该存储器块的状态;-如果找不到满足要求的存储器块,则表示存储器不足,分配失败。

4. 实现最佳适应算法(Best Fit):-遍历链表,找到大小最小的满足要求的空闲存储器块;-将该存储器块标记为已分配,并更新链表中该存储器块的状态;-如果找不到满足要求的存储器块,则表示存储器不足,分配失败。

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

在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。
l.addJob(10,3,jobArray);
System.out.println("...............删除作业2后的内存情况....................");
l.delete(jobArray,2);
System.out.println("...............此后再添加作业4后的内存情况....................");
Link l = new Link();
System.out.println("...................起始的内存..................................");
jobArray[0].print();
System.out.println(".....................增加第一个作业后的内存情况.....................");
实验
一、实验目的
帮助学生理解在不同的存储管理方式下应如何实现主存空间的分配和回收。理解好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能够合理地分配和使用这些存储空间。
二、实验环境
1、Java环境
三、实验时数:

1.在可变分区管理方式下采用最先适应算法实现主存储器的分配和回收。
}
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);

主存空间的分配与回收 首次适应法

主存空间的分配与回收 首次适应法

南通大学操作系统实验课实验报告学生姓名所在院系专业学号指导教师南通大学2014年 5 月 16 日主存空间的分配与回收——首次适应法一、实验目的主存是中央处理机能直接存取指令和数据的存储器,能否合理而有效地使用它,在很大程度上将影响整个计算机系统的性能。

本实验主要熟悉主存的管理方法以及相应的分配与回收算法。

所谓分配,就是解决多道程序或多进程如何共享主存空间的问题,以便各个进程能获得所希望的主存空间,正确运行。

所谓回收,就是当进程运行完成时,将其所占用的主存空间归还给系统。

二、实验要求采用空闲区链法管理空闲区,并增加已分配区表。

分配算法采用首次适应法。

三、设计思路:(1)采用空闲区链法管理空闲区,并增加已分配区表。

分配算法采用首次适应法(内存空闲区的地址按照从小到大的自然顺序排列),实现内存的分配与回收。

(2)设计一个进程申请序列以及进程完成后的释放顺序,实现主存的分配与回收。

(3)进行分配时应该考虑这样3种情况:进程申请的空间小于、等于或大于系统空闲区的大小。

回收时应该考虑这样4种情况:释放区上邻、下邻、上下都邻和都不邻接空闲区。

(4)每次的分配与回收都要求把记录内存使用情况的各种数据结构的变化情况以及各进程的申请、释放情况显示出来。

四、主要思想(1)输入主存空间的最大长度n创建最大长度总和为n的若干空闲区的主存空闲区链;(2)输入待存作业的长度x,从链头开始找第一个合适作业的空闲区:分区长度小于x时,指针后移,继续寻找;分区长度等于x时,分配空间,修改作业分区;分区长度大于x 时,分配空间,修改分区数据。

五、流程图1.空闲区链的首次适应算法分配流程图2.空闲区链的首次适应算法回收流程图六、调试结果1.内存的分配2.内存的回收3.内存清空七、总结与感悟说实话我操作系统学得不是很好,一开始看到题目觉得自己要完成这个实验有些难度。

好在老师提醒书上有另一道类似题目的程序代码,另外书上也有首次适应法的流程图,可以给我们一些提示。

内存分配和内存回收的算法 -回复

内存分配和内存回收的算法 -回复

内存分配和内存回收的算法 -回复内存分配和内存回收是计算机科学中非常重要的概念。

在执行程序时,计算机需要为程序分配一定数量的内存空间来存储变量、数据结构和函数的执行过程。

而内存回收则是指在程序不再需要使用分配的内存空间时,将其释放出来以供其他程序使用。

本文将详细介绍内存分配和内存回收的算法。

一、内存分配算法1. 首次适应算法首次适应算法是最简单的内存分配算法之一。

它从内存的起始位置开始查找第一个可分配的内存块,如果找到大小与需求相匹配的内存块,则将其分配给程序;如果内存块的大小大于需求,则将其分割为两部分,一部分用于分配,另一部分保留在内存中。

此后的分配请求将从上次分配的位置开始查找。

2. 最佳适应算法最佳适应算法是一种贪心算法,它选择大小与需求最相近的可用内存块进行分配。

该算法需要遍历整个内存空间,并找到最小的可用内存块来满足分配请求。

这样可以最大限度地减少内存碎片的产生,但可能需要较长的搜索时间。

3. 最坏适应算法最坏适应算法与最佳适应算法相反,它选择大小最大的可用内存块进行分配。

该算法可以减少外部碎片,但可能导致较多的内部碎片。

该算法适用于大多数内存分配请求都是中等大小的情况。

4. 快速适应算法快速适应算法是一种基于链表的动态分配算法。

它将内存空间划分为多个大小不同的块,并使用链表进行管理。

每个链表对应一个固定大小的内存块,当有分配请求时,只需在对应链表中找到一个可用的内存块即可完成分配。

这种算法具有较快的分配速度和较低的内存碎片率。

5. 分区算法分区算法将内存空间划分为若干固定大小的区域,每个区域可以作为一个分配单元。

当有分配请求时,算法会按照一定的策略(如首次适应、最佳适应等)选择一个区域进行分配,并标记该区域为已分配状态。

当分配完成后,还可以根据需要对已分配的区域进行合并或拆分。

二、内存回收算法1. 引用计数法引用计数法是一种基于引用计数的内存回收算法。

每个对象都包含一个引用计数器,用于记录当前有多少个指针指向该对象。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

操作系统实验四 主存空间的分配与回收-首次适应算法和循环首次适应算法

操作系统实验四 主存空间的分配与回收-首次适应算法和循环首次适应算法

实验报告【实验名称】首次适应算法和循环首次适应算法【实验目的】理解在连续分区动态的存储管理方式下,如何实现主存空间的分配与回收。

【实验原理】首次适应(first fit,FF)算法FF算法要求空闲分区链以地址递增的次序链接。

在分配内存时,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区即可。

然后再按照作业的大小,从该分区中划出一块内存空间,分配给请求者,余下的空闲分区仍留在空闲链中。

若从链首直至链尾都不能找到一个能满足要求的分区,则表明系统中已经没有足够大的内存分配给该进程,内存分配失败,返回。

循环首次适应(next fit,NF)算法为避免低址部分留下许多很小的空闲分区,以及减少查找可用空闲分区的开销,循环首次适应算法在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块玉请求大小相等的内存空间分配给作业。

【实验内容】实现主存空间的分配与回收:1.采用可变式分区管理,使用首次适应算法实现主存空间的分配与回收;2.采用可变式分区管理,使用循环首次适应算法实现主存空间的分配与回收。

数据结构和符号说明:typedef struct PCB//进程控制块{char ProgressName[10]; //进程名称int Startaddress; //进程开始地址int ProgressSize; //进程大小int ProgressState = 0; //进程状态};typedef struct FREE //空闲区结构体{int Free_num; //空闲区名称int Startaddress; //空闲区开始地址int Endaddress; //空闲区结束地址int Free_Space; //空闲区大小};算法流程图:首次适应算法循环首次适应算法程序代码及截图:主界面:首次适应算法,初始空闲区:插入进程:插入3个进程:空闲区信息:删除进程2:删除后空闲区状况:再插入一个进程,可以看到其其初始地址为100:循环首次适应算法,插入3个进程删除进程2后:再插入进程A,发现其从上次找到的空闲分区的下一个空闲分区开始查找,其初始地址为750而不是200:。

操作系统-主存储器空间的分配和回收

操作系统-主存储器空间的分配和回收

实习四 主存储器空间的分配和回收一,实习题目本实习模拟在两种存储管理方式下的主存分配和回收。

第一题:在可变分区管理方式下采用最先适应算法实现主存分配和实现主存回收。

[提示]:可变分区方式是按作业需要的主存空间大小来分割分区的。

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

随着作业的装入、撤离,主存空间被分成许多个分区,有的分为了 说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:第一栏 第二栏其中,起址——指出一个空闲区的主存起始地址。

长度——指出从起始地址开始的一个连续空闲的长度。

状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来登记新的空闲区(例如,作业撤离后,它所占的区域就成了空闲区,应找一个“空表目”栏登记归还区的起址和长度且修改状态)。

由于分区的个数不定,所以空闲区说明表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。

上述的这张说明表的登记情况是按提示(1)中的例所装入的三个作业占用的主存区域后填写的。

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

有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。

为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。

为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。

为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。

(3) 采用最先适应算法(顺序分配算法)分配主存空间。

按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。

实验四:主存空间的分配与回收实验

实验四:主存空间的分配与回收实验

0 10k主存空间的分配和回收一、实验目的设计一个可变式分区分配的存储管理方案。

并模拟实现分区的分配和回收过程。

对分区的管理法可以是下面三种算法之一: 首次适应算法 循环首次适应算法 最佳适应算法二、实验内容和要求主存的分配和回收的实现是与主存储器的管理方式有关的。

所谓分配,就是解决多道作业或多进程如何共享主存空间的问题。

所谓回收,就是当作业运行完成时将作业或进程所占的主存空间归还给系统。

可变分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需求,并且分区个数是可以调整的。

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

随着作业的装入、完成,主存空间被分成许多大大小小的分区,有的分区被作业占用,而有的分区是空闲的。

实验要求使用可变分区存储管理方式,分区分配中所用的数据结构采用空闲分区表和空闲分区链来进行,分区分配中所用的算法采用首次适应算法、循环首次适应算法、最佳适应算法三种算法来实现主存的分配与回收。

同时,要求设计一个实用友好的用户界面,并显示分配与回收的过程。

三、实验主要仪器设备和材料实验环境:硬件环境:IBM-PC 或兼容机 软件环境:Visual C++6.0四、实验原理及设计方案采用可变分区管理,使用首次或最佳适应算法实现主存的分配和回收1、可变分区管理是指在处理作业过程中建立分区,使分区大小正好适合作业的需求,并且分区个数是可以调整的。

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

随着作业的装入、完成,主存空间被分成许多大大小小的分区,有的分区被作业占用,而有的分区是空闲的。

为了说明那些分区是空闲的,可以用来装入新作业,必须有一张空闲说明表 例如:空闲区说明表格式如下:第二栏其中,起址——指出一个空闲区的主存起始地址,长度指出空闲区的大小。

存储管理动态分区分配及回收算法

存储管理动态分区分配及回收算法

存储管理动态分区分配及回收算法介绍存储管理是操作系统中一个重要的功能模块,负责管理计算机的内存资源。

本文将详细探讨存储管理中的动态分区分配及回收算法。

动态分区分配动态分区分配算法是指根据进程的内存需求,在内存中动态地创建分区,并将进程加载到相应的分区中。

下面是几种常见的动态分区分配算法。

1. 首次适应算法首次适应算法是最简单、最直观的动态分区分配算法。

它从内存的起始位置开始搜索,找到第一个能满足进程需求的分区即可。

具体步骤如下:1.初始化内存的空闲分区表,记录内存中每个空闲分区的起始地址和长度。

2.当一个进程需要分配内存时,遍历空闲分区表,找到第一个大小能满足进程需求的分区。

3.如果找到了合适的分区,将进程加载到该分区,并更新空闲分区表。

4.如果没有找到合适的分区,则提示内存不足。

首次适应算法的优点是简单、快速,但可能会导致碎片问题。

2. 最佳适应算法最佳适应算法是指选择与进程需求最接近的、且大小大于等于进程需求的分区。

具体步骤如下:1.初始化内存的空闲分区表。

2.当一个进程需要分配内存时,遍历空闲分区表,找到满足进程需求的最小分区。

3.如果找到了合适的分区,将进程加载到该分区,并更新空闲分区表。

4.如果没有找到合适的分区,则提示内存不足。

最佳适应算法能最大程度地减少碎片问题,但执行效率较低。

3. 最差适应算法最差适应算法是指选择与进程需求最接近的、且大小大于等于进程需求的最大分区。

具体步骤如下:1.初始化内存的空闲分区表。

2.当一个进程需要分配内存时,遍历空闲分区表,找到满足进程需求的最大分区。

3.如果找到了合适的分区,将进程加载到该分区,并更新空闲分区表。

4.如果没有找到合适的分区,则提示内存不足。

最差适应算法能最大程度地降低内存碎片,但执行效率相对较低。

4. 快速适应算法快速适应算法是一种基于空闲分区表大小的快速搜索算法。

具体步骤如下:1.初始化内存的空闲分区表。

2.当一个进程需要分配内存时,根据进程需求的大小,在空闲分区表中选择一个合适的分区。

内存的分配与回收实验报告(最先适应法)

内存的分配与回收实验报告(最先适应法)

代码实现如下:#include <stdio.h>#include <malloc.h>#include <stdlib.h>#define n 64 //定义内存的大小int a[n],count=0;//数组a用来保存内存使用状况1为已分配0为未分配,count用来记name数组中元素个数char name[n];//已分配内存的名称(字符类型)typedef struct linknode{char pid;int start;int length;struct linknode *left,*right;}de_node; //进程节点结构体定义//head1表示未分配内存队列头指针,head2便是已分配进程队列头指针de_node *head1,*head2=NULL;struct linknode* creat()//创建一个进程节点{int len,flag1=1;//用于表示进程是否可以创建char id;struct linknode* p;p = (de_node *)malloc(sizeof(de_node));//试图在系统内存中开辟空间创建一个进程if (p==NULL) //p为空,说明系统没有可用内存用于创建此模拟进程{ printf("系统没有足够的内存可供使用!\n");//输出return(NULL);//返回空指针}printf("请输入进程id(字符类型)和长度:");//为进程输入id和分配的长度scanf("%c %d",&id,&len);fflush(stdin);//清除输入缓存if((id>='a'&&id<='z'||id>='A'&&id<='Z')&&(len>0)){for(int i=0;i<count;i++)//判断输入的进程名,如果已使用,返回空指针,并释放p指针if(name[i]==id){printf("此名称进程已存在!!");flag1=0;//标志位为0,表示下面对p指向内容不做修改free(p);return NULL;}if(len==0) {//如果输入要分配的进程长度为0,释放p,返回空指针printf("输入长度为0!\n");free(p);return(NULL);}if(flag1){//标志位1,可以对p指向内容进行修改p->pid=id; //idp->start=0; //初始开始内存位置,在以后会修改p->length=len;//长度p->left=NULL;//左指针p->right=NULL;//右指针name[count++]=id;//将id存入数组,count自加return(p);}//返回创建的进程的地址}else {printf("输入进程格式有误\n");free(p);return (NULL);}}//分配内存空间void distribute(de_node *p){ de_node *q=head1,*temp;int flag=0;do{//do_while循法//判断当前指向的内存空间的长度是否满足p所申请的长度,大于就分配if(q->length>=p->length) {p->start=q->start;//把进程的内存开始地址指向内存的可用开始地址处q->start+=p->length;//可用地址起始改变q->length-=p->length;//可用内存长度修改for(int i=p->start;i<p->start+p->length;i++)//将已分配的内存空间全部置1 a[i]=1;flag=1;//表示内存可分配//队列不止一个进程,第一个满足条件,并且刚好分配完,修改指针指向if(q->length==0&&q->right!=q) { if(q==head1)//如果第一个满足,修改头指针指向head1=q->right;q->left->right=q->right;q->right->left=q->left;free(q);//把这个已分配完的空间指针释放}}if(flag==1)//已做完处理直接跳出循环break;if(flag==0)//当前指向的内存不满足,指向下一个,继续判断是否满足q=q->right;}while(q!=head1);//搜索一遍可用内存序列if(flag==0){//没有可用的内存printf("没有满足的内存!\n");count--;//由于创建时加1,但在分配内存时失败,把1又减掉free(p);//把这个未分配到内存的进程释放}if(flag==1){//表示上面已分配好内存,并已修改内存链表,下面修改已分配内存的进程队列temp=head2;//把已分配内存的进程队列赋值给临时指针if(temp==NULL)//如果还还没有存在的任何的进程,说明当前是第一个{ head2=p;//让头指针指向第一个进程p->left=p;//双向队列第一个左右指针都指向自己p->right=p;//双向队列第一个左右指针都指向自己}else if(temp!=NULL){//已存在队列,把当前直接链到第一个,与上面的区别是指针指向head2=p;//让头指针指向p指向的进程p->left=temp->left;//p进程左边为原来第一个的左边p->right=temp;//p进程右边指向第一个temp->left->right=p;//原来第一个的左边为ptemp->left=p;//原来第一个的左边的进程为p}}}//对进程的回收void reclaim(){ char id;int flag=0;de_node *q=head2,*p=head1;if(head2==NULL)//表示当前没有进程{ printf("已没有进程!\n");}else {//已分配内存队列如果不为空printf("输入要回收的进程id:");//输入要回收进程的idscanf("%c",&id);fflush(stdin);for(int i=0;i<count;i++)//双重循环把要回收的进程找出来,并把记录的id去掉if(name[i]==id){//判断当前的进程是否满足要求for(int j=i;j<count;j++)name[j]=name[j+1];//向前覆盖name[j+1]=NULL;//置空count--;//减一}//判断是否总共只有一个进程且是够刚好也满足条件if(q->pid==id&&q->right==q&&head2==q){ head2=NULL;//把已分配队列直接置空flag=1;//表示找到满足条件的进程}if(flag==0){//上面的都没找到do{if(q->pid==id){//如果找到if(q==head2)head2=q->right;q->left->right=q->right;//修改指针指向q->right->left=q->left;flag=1;break;}else q=q->right;}while(q!=head2);}//如果找到或是遍历一遍结束if(flag==0) printf("没有此进程号!!!\n");//没有找到满足的进程if(flag==1){//表示找到了for(int i=q->start;i<q->start+q->length;i++)//释放占有的内存a[i]=0;//接下来修改可用内存的队列,while(q->start>p->start&&p->right!=head1){//从第一个开始找到回收回来的内存开始地址大的那个队列p=p->right;}if(p==head1)//表示比第一个的开始还小,那么就要修改头地址head1=q;//其他情况不用修改头地址,只需找到应该的位置,把此进程插进去q->left=p->left;//修改指针的指向q->right=p;p->left->right=q;p->left=q;if(q->start+q->length==p->start)//可以与后面合并的情况{ q->length+=p->length;//修改指针的指向p->right->left=q;q->right=p->right;free(p);}if(q->left->start+q->left->length==q->start)//可以与前面合并的情况{ q->left->length+=q->length;//修改指针的指向q->left->right=q->right;q->right->left=q->left;free(q);}}}}//打印输出void print(){ de_node *q=head2,*p=head1;if(count==0)printf("没有进程占有内存。

操作系统 主存储器空间的分配和回收

操作系统 主存储器空间的分配和回收

实习四 主存储器空间的分配和回收一,实习题目本实习模拟在两种存储管理方式下的主存分配和回收。

第一题:在可变分区管理方式下采用最先适应算法实现主存分配和实现主存回收。

[提示]:可变分区方式是按作业需要的主存空间大小来分割分区的。

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

随着作业的装入、撤离,主存空间被分成许多个分区,有的分为了 说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:第一栏 第二栏其中,起址——指出一个空闲区的主存起始地址。

长度——指出从起始地址开始的一个连续空闲的长度。

状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区;另一种是“空表目”状态,表示表中对应的登记项目是空白(无效),可用来登记新的空闲区(例如,作业撤离后,它所占的区域就成了空闲区,应找一个“空表目”栏登记归还区的起址和长度且修改状态)。

由于分区的个数不定,所以空闲区说明表中应有适量的状态为“空表目”的登记栏目,否则造成表格“溢出”无法登记。

上述的这张说明表的登记情况是按提示(1)中的例所装入的三个作业占用的主存区域后填写的。

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

有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。

为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。

为此,在空闲区说明表中,把每个空闲区按其地址顺序登记,即每个后继的空闲区其起始地址总是比前者大。

为了方便查找还可使表格“紧缩”,总是让“空表目”栏集中在表格的后部。

(3) 采用最先适应算法(顺序分配算法)分配主存空间。

按照作业的需要量,查空闲区说明表,顺序查看登记栏,找到第一个能满足要求的空闲区。

使用最佳适应算法设计主存的分配和回收程序c语言

使用最佳适应算法设计主存的分配和回收程序c语言

使用最佳适应算法设计主存的分配和回收程序c语言最佳适应算法是一种主存分配与回收策略,旨在有效利用计算机主存资源,最大化系统性能和用户体验。

这篇文章将详细介绍最佳适应算法的原理和实现,并使用C语言编写相应的主存分配和回收程序。

首先,我们需要了解最佳适应算法是如何工作的。

最佳适应算法基于以下两个基本原则:1. 内存分配:当我们需要分配一块内存时,最佳适应算法会在主存中寻找能够容纳所需大小的最小空闲块,并将其分配给请求者。

这意味着最佳适应算法会尽可能地减少浪费的空间。

2. 内存回收:当一块内存被释放后,最佳适应算法会尝试与相邻的空闲块进行合并,以形成更大的连续空闲块。

这样做可以最大化主存资源的利用率。

有了这些基本原则作为指导,接下来我们将通过实现一个主存分配和回收模拟程序来展示最佳适应算法的工作原理。

我们将使用C语言来编写这个程序。

首先,我们需要定义一个数据结构来表示主存中的内存块。

这个数据结构应该包含当前内存块的起始地址、大小和是否已分配的标志。

下面是相应的代码:ctypedef struct {int start_address;int size;int allocated;} MemoryBlock;接下来,我们需要定义一个数据结构来管理主存中的所有内存块。

我们可以使用一个数组来存储这些内存块。

此外,我们还需要跟踪主存中的空闲块数目。

下面是相应的代码:c#define MAX_BLOCKS 100MemoryBlock memory[MAX_BLOCKS];int num_free_blocks = 1;在程序初始化阶段,我们需要初始化主存数据结构,即将整个主存划分为一个初始的空闲块。

下面是相应的代码:cvoid initialize_memory(int size) {memory[0].start_address = 0;memory[0].size = size;memory[0].allocated = 0;}接下来,我们需要实现主存分配函数。

内存分配,首次适应算法

内存分配,首次适应算法

一、实验名称:存分配与回收二、实验容:用首次适应算法实现存储空间的分配,回收作业所占用的存储空间。

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

当用户提出申请主存空间的要求时,存储管理能够按照一定的策略分析主存的使用情况,找出足够的空间分配给申请者;当作业运行完毕,存储管理要回收作业占用的主存空间。

本实验实现在可变分区存储管理方式下,采用最先适应算法对主存空间进行分配和回收,以加深了解操作系统的存储管理功能。

四、实验过程:a)基本思想空闲分区链以地址递增的次序连接。

在分配存时,从链首开始顺序查找,直至找到一个大小能够满足要求的空闲分区为止;然后再按照作业大小,从该分区中划出一块存空间分配给请求者,余下的空闲分区仍然留在空闲链中。

若从链首直至链尾都不能找到一个能满足要求的分区,则此次存分配失败。

b)主要数据结构typedef struct FreeLink{ //空闲链struct FreeLink *prior;char name;int start;int size;bool flag;struct FreeLink *next;}* ptr,*head;head top;ptr p;c)存分配算法当有进程要求分配主存时,依据首次适应算法从链头开始,延链查找一个足以容纳该进程的空闲区。

若这个分区比较大,则一分为二,一部分分配给进程,另一部分作为空闲区仍留在链中的当前位置,修改它的上一个空闲区的前向指针值为再加上分配给进程的分区大小,下一个空闲区的后向指针值为再加上分配给进程的分区大小,使链保持完整。

若这个分区的大小正好等于进程的大小,该分区全部分配给进程,并将该空闲区从链中摘除(即修改下一个空闲区的后向指针=该空闲区后向指针,上一个空闲区的前向指针=该空闲区的前向指针)。

再在已分配区表中找一个空表目,登记刚刚分配的存始址、长度和进程号。

内存回收首适应算法实验报告

内存回收首适应算法实验报告

操作系统实验报告——首适应算法实验报告计科101班张昊翔1007300204一.实验目的在计算机系统中,为了提高内存区的利用率,必须给电脑内存区进行合理的分配。

本实验通过对内存区域分配方法首次适应算法的使用,来了解内存的分配的模式。

二.实验要求1.内存大小初始化2.可以对内存区进行动态分配,采用首次适应算法来实现3.可以对已经分配的内存块进行回收,并合并相邻的空闲的内存块三.实验内容把一个作业装入内存,按首次适应算法对内存进行分配,作业结束,回收已经分配给该作业的内存块,并合并相邻的空闲内存块。

四.主要思想首次适应算法要求空闲分区链以地址递增的次序链接。

在分配内存时,从链首开始查找,直到找到一个大小能满足要求的空闲分区为止;然后按照作业大小,从该分区中划出一块内存空间分配给请求者,余下的空闲区仍留在空闲链中。

若从链首到链尾都不能找到一个能满足要求的分区,则此次分配失败。

五.程序流程图次适应算法的结构如图四.源代码// bank2.cpp : 定义控制台应用程序的入口点。

//#include"stdafx.h"// TODO: 在STDAFX.H 中// 引用任何所需的附加头文件,而不是在此文件中引用#include<STDIO.H>#include<STDLIB.H>int MAX_SEGMENT=10;//最大碎片值struct Partition //分区表目{ int Par_Size; //分区大小int Par_No; //分区序号或者名字int Addr; //分区地址int IsUse; //分区使用情况,0表示空闲表示使用Partition *pri; //前向指针Partition *next; //后向指针};Partition * Int()//函数返回Partition类型指针{ //初始化空闲分区表Partition *list,*H,*H1;list=(struct Partition *)malloc(sizeof(struct Partition));list->next=NULL; H=list;if(!list) { printf("\n错误,内存初始化分配失败程序结束");exit(1); }H1=(struct Partition *)malloc(sizeof(struct Partition));printf("请预先输入分区总大小(以KB为单位)");scanf_s("%d",&H1->Par_Size);H1->Addr=0; H1->Par_No=0;H1->IsUse=0; H1->pri=H; H1->next=NULL; H->next=H1;////list--->H1return list; }Partition * InitFP() { //初始化已分配分区表Partition *FP,*F,*H; int i;FP=(struct Partition *)malloc(sizeof(struct Partition));FP->next=NULL;H=FP;for(i=0;i<10;i++) //已分配区先暂定分配十个表目{F=(struct Partition *)malloc(sizeof(struct Partition));if(!F){ printf("\n错误,内存分配失败程序结束");exit(1); }F->Par_Size=0;F->Addr=0; F->Par_No=0;F->IsUse=0; F->next=NULL;H->next=F; F->pri=H; H=H->next; }return FP; }Partition * New_Process( Partition *list, Partition *FP) { //为新的进程分配资源Partition *H,*P,*H1;int Size,Name,L;H=list; H1=FP->next; H=H->next;printf("请输入新作业的名称和大小(整数):");scanf_s("%d %d",&Name,&Size);while(H){ if(!H) //表目已查完,无法分配{ printf("\n已无空闲分区,本次无法分配!");return list; }else{ if(H->IsUse==0) //空表目 //if(H->Par_Size>=Size) //大小满足,空闲分区大小》要分配的大小if(H->Par_Size>=Size) //大小满足,{ bool temp=false;if((H->Par_Size-Size)<=MAX_SEGMENT){//空闲分区大小-要分配的大小<碎片值,会产生碎片,将整块内存大小分配出去Size=H->Par_Size;//分配的大小为整块内存temp=true;//会产生碎片} //其他情况就分配大小为请求大小不会产生碎片L=H->Addr;//保存空闲分地址if(temp){printf("该次内存分配会产生碎片,将整块内存大小%d分配出去!",Size);}else{ printf("该次内存分配不会产生碎片");} break; }}H=H->next; //否则继续往下查找} if(H) {if(H->Par_Size>Size) //大小满足,空闲分区大小》要分配的大小{ P=(struct Partition *)malloc(sizeof(struct Partition)); //分配新的表目处理一条数据分配一次内存P->IsUse=1; P->Addr=L;//指向空闲分区地址P->next=H; //修改指针H->pri->next=P;P->pri=H->pri;H->pri=P;P->Par_Size=Size;//分配大小为要请求分配的大小P->Par_No=Name;//名称H->Par_Size-=Size; //修改空闲分区,H所指区块大小减SizeH->Addr+=Size;//H所指区块地址加Size}else { H->IsUse=1; //大小相等的 把当前表项设置空表目}while(H1) {if(H1->IsUse==0){ H1->Par_No=Name; H1->Par_Size=Size;H1->Addr=L;//保存已分配地址H1->IsUse=1;//在已分配表中设置为已分配break; }H1=H1->next;} }else printf("所申请资源已大过系统所拥有的,请重新输入!\n");return list; }Partition *Reclaim( Partition *list, Partition *FP){//结束作业,资源回收,No为作业名 回收内存Partition * H1,*H2,*H3,*HF;//H1为释放区 H2为后分区 H3为前分区int No; //作业名H1=list;HF=FP;//可有可无H1=H1->next;HF=FP->next;printf("请输入您想结束的作业名:");scanf_s("%D",&No);while(HF)//对已分配表进行操作{if(HF->Par_No==No){HF->IsUse=0; //标志为空表目break;//这时保存着HF所指分区的信息}HF=HF->next;} if(!HF) //如果找不到该作业 则提示出错printf("所输入的作业名称不正确,请重新输入!");else{while(H1)//对空闲表进行操作{if(H1->Par_No==No){H1->IsUse=0; //标志为空表目printf("内存回收成功");break;}H1=H1->next;}H2=H1->next;//后分区H3=H1->pri;//前分区if(H2&&H2->IsUse==0) //后接分区为空闲{if(H2->next==NULL) //判断后接分区是否为尾结点{H1->Par_Size+=H2->Par_Size; //把H2合并到H1H1->next=NULL;free(H2);printf("已回收%d大小内存",H1->Par_Size); }else//后分区不为空闲表示已经被使用{ H1->Par_Size+=H2->Par_Size;H1->next=H2->next; H2->next->pri=H1;free(H2); printf("已回收%d大小内存",H1->Par_Size);}}if(H3&&H3->IsUse==0) //前分区为空闲分区则合并去前分区{H3->Par_Size+=H1->Par_Size;H3->next=H1->next;if(H1->next!=NULL) //若H1为尾结点H1->next->pri=H3;free(H1);printf("已回收%d大小内存",H1->Par_Size);}}return list;}void Print( Partition *list, Partition *FP){ //输出已分配分区和空闲分区Partition *H1,*H2;H1=list->next;H2=FP; H2=H2->next;printf("****************已分配分区表*******************\n");printf("分区序号大小始址状态\n");while(H2){printf("%d %d %d",H2->Par_No,H2->Par_Size,H2->Addr);if(H2->IsUse==1)printf(" 已分配\n");elseprintf(" 空表目\n");H2=H2->next;}printf("**************************************************\n");printf("****************总的空闲分区表*******************\n");printf("分区序号大小始址状态\n");while(H1){printf("%d %d %d",H1->Par_No,H1->Par_Size,H1->Addr);if(H1->IsUse==1)printf(" 已分配\n");elseprintf(" 空表目\n");H1=H1->next;}printf("**************************************************\n");}void Main_Print( Partition *list, Partition *FP){ //主入口函数 进行菜单选择int op;while(1){ printf("\n 主菜单\n");printf("1.申请新的作业,分配内存\n");printf("2.结束作业,回收内存\n");printf("3.查看内存表\n");printf("4.退出系统\n");printf("\n请选择:");scanf_s("%d",&op);switch(op) //根据输入,选择分支方向{case 1: New_Process(list,FP); break;case 2: Reclaim(list,FP); break;case 3: Print(list,FP); break;case 4: break; default:printf("\n选择错误,请重新选择!");break;}if(op==4) break; //退出循环}}int main() { //主函数入口struct Partition *list,*FP;list=Int();FP=InitFP();Main_Print(list,FP); }五.输入输出。

用首次适应算法实现内存分配与回收

用首次适应算法实现内存分配与回收

#include"stdafx.h"#include<iostream>#include<iomanip>using namespace std;//全局变量int count1=0;int count2=0;#define m 10 //假定系统允许的空闲区表最大为m#define n 10 //假定系统允许的最大作业数量为n#define number 128 //内存大小//空闲区表的定义:struct{int name; //项目名float start; //空闲区起始地址float length; //空闲区长度,单位为字节int state; //空闲区表登记栏标志,用"0"表示空表目,用"1"表示空闲,"2"表示释放}free_table[m],tmp; //空闲区表对象名//已分配表的定义struct{int name; //名字float start; //已分分区起始地址float length; //已分分区长度,单位为字节int state; //已分配区表登记栏标志,"0"表示没有,不显示,"1"表示已经分配}used_table[n]; //已分配区表对象名//初始化两个表void init(){int i;for(i=0; i<n; i++)used_table[i].state=0; //已分配表的表项全部置为不存在,不能显示free_table[0].name=1;free_table[0].start=0;free_table[0].length=number; //初始长度为free_table[0].state=1; //空闲区表的第一个表项为未分配count1++; //空闲区增加一个初始表项}void show(int a1,int a2) //程序执行时输出模拟的内存分配回收表{cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"+++++++ 空闲区+++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"分区号"<<" "<<"起始地址"<<" "<<"作业长度"<<" "<<"状态"<<endl;for(int i=0;i<a1;i++){if(free_table[i].state==1)cout<<free_table[i].name<<" "<<free_table[i].start<<"KB"<<""<<free_table[i].length<<"KB"<<" "<<"未分配"<<endl;elsecout<<free_table[i].name<<" "<<"---"<<" "<<"---"<<" "<<"空表目"<<endl;}cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"+++++++ 已分配区++++++\n";cout<<"+++++++++++++++++++++++++++++++++++++++\n";cout<<"分区号"<<" "<<"起始地址"<<" "<<"作业长度"<<endl;for(int j=0;j<a2;j++){if(used_table[j].state==1) //显示已分配的内存{cout<<used_table[j].name<<"\t "<<used_table[j].start<<"KB"<<"\t"<<used_table[j].length<<"KB"<<endl;}}}//首次适应算法int first_fit(int process_name, float need_length){int i=0;//在空闲区找适合的空间for(i=0;i<m;i++) //已经存在的分区号不分配{if(free_table[i].name==process_name&&free_table[i].state==1){cout<<"分区号已经存在!"<<endl;return 0;}}for(i=0;i<m;i++){while(free_table[i].state==1) //在未分配中找合适的{if(need_length==free_table[i].length) //找到大小相等的未分配{used_table[count2].name=process_name; //分配used_table[count2].start=free_table[i].start;used_table[count2].length=free_table[i].length;used_table[count2].state=1;count2++; //计数加一free_table[i].state=0; //空闲区表项状态变为空表目free_table[i].name=process_name; //空闲区的名字换为新的申请名show(count1,count2);return 0;}elseif(need_length<free_table[i].length) //找到较大的未分配{used_table[count2].name=process_name; //分配used_table[count2].start=free_table[i].start;used_table[count2].length=need_length;used_table[count2].state=1;free_table[i].start=free_table[i].start + need_length; //开始地址后移free_table[i].length=free_table[i].length - need_length; //长度减少tmp=free_table[i]; //存储free_table[i]for(int l=n-1;l>i;l--)free_table[l]=free_table[l-1]; //原来的未分配被分成两块,一块空项目,一块未分配,i后的项目后移free_table[i+1]=tmp; //赋值free_table[i].name=process_name; //原来被分配的内存成了空项目free_table[i].start=used_table[count2].start;free_table[i].length= used_table[count2].length;free_table[i].state=0;count1++; //空闲区增加一个空表目count2++; //已分配数加一show(count1,count2);return 0;}elseif(i!=m-1) //继续遍历i++;else//没找到{cout<<"没找到合适的空闲区,分配失败!"<<endl;return 0;}}}return 0;}void show_distribute() //显示分配后的情况{int pname;float nlength;cout<<"请输入分区号:";cin>>pname;cout<<"分区长度:";cin>>nlength;getchar();first_fit(pname,nlength);}//回收算法int recycle(int process_name){int y;float recycle_start, recycle_length=0;int i, j, k; //j栏是下邻空闲区,k栏是上栏空闲区int x;//在内存分配表中找到要回收的作业for(y=0;y<n;y++){if(used_table[y].name==process_name){recycle_start=used_table[y].start;recycle_length=used_table[y].length;used_table[y].state=0; //状态置,被回收for(int l=y;l<n;l++) //前移一个used_table[l]=used_table[l+1];count2--; //项目数减一}}while(recycle_length==0) //没找到{cout<<"要回收的主存不存在!"<<endl;return 0;}j=k=-1;i=0;for(i=0;i<m;i++) //修改空闲分区表{if(free_table[i].state==1){if((free_table[i].start+free_table[i].length)==recycle_start)k=i; //判断上邻接if((recycle_start+recycle_length)==free_table[i].start)j=i; //判断下邻接}}//合并空闲区if(k!=-1) //回收区有上邻接{if(j!=-1){ //回收区也有下邻接,和上下领接合并free_table[k].length +=free_table[j].length+recycle_length;tmp=free_table[k];for(int l=k;l<m;l++) //前移两个{free_table[l]=free_table[l+1];}for(int r=k;r<m;r++){free_table[r]=free_table[r+1];}free_table[k]=tmp;count1-=2;if(free_table[0].length==128)free_table[0].name=1;show(count1,count2);return 0;}else//不存在下邻接,和上邻接合并{tmp=free_table[k];for(int l=k;l<m;l++) //前移一个free_table[l]=free_table[l+1];free_table[k]=tmp;free_table[k].length +=recycle_length;count1--;if(free_table[0].length==128)free_table[0].name=1;show(count1,count2);return 0;}}else if(j!=-1){ //只有下邻接,和下邻接合并tmp=free_table[j];for(int l=j-1;l<m;l++) //前移一个free_table[l]=free_table[l+1];free_table[j-1]=tmp;free_table[j-1].name=process_name;free_table[j-1].start=recycle_start;free_table[j-1].length +=recycle_length;count1--;if(free_table[0].length==128)free_table[0].name=1;show(count1,count2);return 0;}else{ //上下邻接都没有for(x=0;x<m;x++){while(free_table[x].name==process_name){free_table[x].state=1; //直接将空表目状态改为“”if(free_table[0].length==128)free_table[0].name=1;show(count1,count2);return 0;}}}return 0;}void show_recycle(){int pname;cout<<"请输入您要释放的分区号:";cin>>pname;getchar();recycle(pname);}int main() //主函数调用各功能函数对所有工作进行测试{int choice; //用来选择将要进行的操作bool exitFlag=false;cout<<" 动态分区分配方式的模拟\n";cout<<"************************************\n";cout<<"请选择操作类型:\n";init(); //开创空闲区和已分配区两个表show(1,0);while(!exitFlag){cout<<"********************************************\n";cout<<"** 1: 分配内存2: 回收内存**\n";cout<<"** 3:查看内存分配0: 退出**\n";cout<<"********************************************\n";cout<<"请输入您的操作:";cin>>choice;switch(choice){case 0:exitFlag=true; //退出操作break;case 1:show_distribute(); // 分配内存break;case 2:show_recycle(); //回收内存break;case 3:show(count1,count2); //显示分配break;default: cout<<"不存在的指令!"<<endl; break;}}}。

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

主存空间的分配与回收—
首次适应法
This manuscript was revised by the office on December 10, 2020.
南通大学操作系统实验课
实验报告
学生姓名
所在院系
专业
学号
指导教师
南通大学
2014年 5 月 16 日主存空间的分配与回收
——首次适应法
一、实验目的
主存是中央处理机能直接存取指令和数据的存储器,能否合理而有效地使用它,在很大程度上将影响整个计算机系统的性能。

本实验主要熟悉主存的管理方法以及相应的分配与回收算法。

所谓分配,就是解决多道程序或多进程如何共享主存空间的问题,以便各个进程能获得所希望的主存空间,正确运行。

所谓回收,就是当进程运行完成时,将其所占用的主存空间归还给系统。

二、实验要求
采用空闲区链法管理空闲区,并增加已分配区表。

分配算法采用首次适应法。

三、设计思路:
(1)采用空闲区链法管理空闲区,并增加已分配区表。

分配算法采用首次适应法(内存空闲区的地址按照从小到大的自然顺序排列),实现内存的分配与回收。

(2)设计一个进程申请序列以及进程完成后的释放顺序,实现主存的分配与回收。

(3)进行分配时应该考虑这样3种情况:进程申请的空间小于、等于或大于系统空闲区的大小。

回收时应该考虑这样4种情况:释放区上邻、下邻、上下都邻和都不邻接空闲区。

(4)每次的分配与回收都要求把记录内存使用情况的各种数据结构的变化情况以及各进程的申请、释放情况显示出来。

四、主要思想
(1)输入主存空间的最大长度n创建最大长度总和为n的若干空闲区的主存空闲区链;
(2)输入待存作业的长度x,从链头开始找第一个合适作业的空闲区:分区长度小于x时,指针后移,继续寻找;分区长度等于x时,分配空间,
修改作业分区;分区长度大于x时,分配空间,修改分区数据。

五、流程图
1.空闲区链的首次适应算法分配流程图
2.空闲区链的首次适应算法回收流程图
六、调试结果
1.内存的分配
2.内存的回收
3.内存清空
七、总结与感悟
说实话我操作系统学得不是很好,一开始看到题目觉得自己要完成这个实验有些难度。

好在老师提醒书上有另一道类似题目的程序代码,另外书上也有首次适应法的流程图,可以给我们一些提示。

之后我也参考了网上的相关资料,看看别人是如何实现的,他们都是怎么样的思路和方法,与我一开始的想法相比,比我精妙在哪里。

最后自己调试时,遇到了许许多多问题和错误,请教了学得比较好的同学、经过不断的修改和完善之后,终于做完实验。

这次的实验使我了解到,平时对知识的积累相当重要,同时也要注重课上老师的讲解,老师在课上的延伸是课本上所没有的,这些知识对于我们对程序的编写有很大的作用,同时,编程也要求我们有足够的耐心,细细推敲。

越着急可能就越无法得到我们想要的结果,遇到不会的问题要多多请教,知识是在实践与向别人请教的过程中积累的,所以问是至关重要的,只要肯下功夫很多东西都是可以完成的。

操作系统这门课不但重要而且十分有用,我一定要下功夫把这门课学好。

相关文档
最新文档