循环首次适应的动态分区分配算法模拟

合集下载

采用首次适应算法的动态分区分配模拟课程设计实验报告

采用首次适应算法的动态分区分配模拟课程设计实验报告

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来与空闲分区进行区别。

循环首次适应的动态分区分配算法模拟

循环首次适应的动态分区分配算法模拟

循环首次适应的动态分区分配算法模拟1.初始化内存空间为一个整体的空闲块。

2.当进程请求内存空间时,多次内存空闲块的循环链表,直到找到一个合适大小的空闲块为止。

3.如果找到了合适的空闲块,则将其划分为两个部分,一个部分给予进程使用,另一个部分保留为新的空闲块。

4.如果未找到合适的空闲块,则表示内存空间不足,需要进行深度缺页异常处理。

以下是一个循环首次适应算法的模拟过程:1.假设一个内存空间大小为1000KB,初始时为一个整体的空闲块。

2.进程A请求100KB的内存空间,开始内存空闲块链表。

3.如果找到合适的空闲块(大小≥100KB),则将其划分为两个部分,一个部分分配给进程A,另一个部分保留为新的空闲块。

4.进程B请求200KB的内存空间,继续内存空闲块链表。

5.如果找到合适的空闲块(大小≥200KB),则将其划分为两个部分,一个部分分配给进程B,另一个部分保留为新的空闲块。

6.进程C请求150KB的内存空间,继续内存空闲块链表。

7.找到合适的空闲块(大小≥150KB),将其划分为两个部分,一个部分分配给进程C,另一个部分保留为新的空闲块。

8.进程D请求300KB的内存空间,继续内存空闲块链表。

但此时已经循环了一次,仍未找到合适的空闲块。

9.进行深度缺页异常处理,即向操作系统申请更多的内存空间。

10.操作系统分配一块500KB的空闲块给进程D。

11.继续内存空闲块链表,找到合适的空闲块(大小≥300KB)。

12.将其划分为两个部分,一个部分分配给进程D,另一个部分保留为新的空闲块。

13.进程E请求250KB的内存空间,继续内存空闲块链表。

14.找到合适的空闲块(大小≥250KB),将其划分为两个部分,一个部分分配给进程E,另一个部分保留为新的空闲块。

15.当所有进程运行完毕后,剩余的空闲块可以继续加入链表,供下一次的分配请求使用。

总结起来,循环首次适应算法通过循环链表合适大小的空闲块来满足进程的内存需求,能够最大限度地利用内存空间,避免了内存碎片的产生。

最好适应动态分区分配算法模拟

最好适应动态分区分配算法模拟

最好适应动态分区分配算法模拟动态分区分配算法是操作系统中的一种管理内存分配的方法,它可以根据实际需求动态地分配和回收内存。

在动态分区分配算法中,内存被划分为多个较小的区域,每个区域可以被分配给一个进程使用。

当一个进程结束后,它所占用的内存可以被回收,并重新分配给其他进程使用。

以下是一个模拟动态分区分配算法的例子。

假设系统中有4个进程需要申请内存空间,它们的大小分别是:P1(100KB)、P2(200KB)、P3(400KB)、P4(300KB)。

本例中我们采用首次适应算法(First Fit)来模拟动态分区分配。

首次适应算法是指内存分区按大小顺序排列,当有一个进程需要内存分配时,系统从低地址到高地址进行,找到一个能满足所需大小的内存分区即可。

以下是该算法的详细步骤:1.初始化内存分区列表。

假设系统中的内存总大小为1000KB,起始地址为0KB,结束地址为1000KB。

此时内存分区列表为空。

2.进程P1申请100KB的内存空间。

内存分区列表,找到第一个大小大于等于100KB的空闲分区,假设为Q1(大小为200KB)。

将分区Q1划分为两个部分:一个部分给进程P1使用,大小为100KB;另一个部分留作未分配区,大小为100KB。

更新内存分区列表,添加两个分区:分区Q1(已分配给P1)和分区Q2(未分配区,大小为100KB)。

此时内存分区列表为:Q1(100KB,已分配给P1)、Q2(100KB,未分配区)。

3.进程P2申请200KB的内存空间。

内存分区列表,找到第一个大小大于等于200KB的空闲分区,假设为Q3(大小为400KB)。

将分区Q3划分为两个部分:一个部分给进程P2使用,大小为200KB;另一个部分留作未分配区,大小为200KB。

更新内存分区列表,添加两个分区:分区Q3(已分配给P2)和分区Q4(未分配区,大小为200KB)。

此时内存分区列表为:Q1(100KB,已分配给P1)、Q2(100KB,未分配区)、Q3(200KB,已分配给P2)、Q4(200KB,未分配区)。

实验五动态分区分配算法的模拟

实验五动态分区分配算法的模拟

实验五动态分区分配算法的模拟为了更好地理解动态分区分配算法的工作原理,我们可以进行一次模拟实验。

在实验中,我们将模拟一个内存分区,并使用动态分区分配算法来管理这些分区。

首先,让我们定义一个内存大小为1000字节的分区。

我们假设这个内存中包含几个已分配的分区和几个空闲的分区。

我们使用首次适应算法来进行分区的首次适应分配。

首先,我们将整个内存空间标记为空闲状态,并创建一个初始的空闲链表。

我们假设初始时只有一个空闲分区,大小为1000字节,起始地址为0。

现在,假设有一个进程请求分配一个250字节大小的内存空间。

我们首先检查空闲链表,找到一个大小大于等于250字节的空闲分区。

在这种情况下,我们发现第一个空闲分区的大小是1000字节,所以我们将它拆分成250字节的已分配分区和750字节的空闲分区。

我们在已分配分区上标记一个进程编号,并将空闲分区加入空闲链表。

接下来,假设我们的进程需要申请500字节的内存空间。

在这种情况下,我们需要查找一个大小大于等于500字节的空闲分区。

我们发现第一个可用的空闲分区大小是750字节,我们将它拆分为已分配的500字节和剩余的250字节的空闲分区。

然后,我们假设有进程释放了先前分配的250字节的内存空间。

当一个进程释放分配的内存空间时,我们需要合并相邻的空闲分区。

在这种情况下,释放的分区位于地址0,大小为250字节,并且其下一个分区是地址500,大小为500字节的空闲分区。

因此,我们将这两个分区合并为一个大小为750字节的空闲分区。

接下来,我们假设另一个进程将请求600字节的内存空间。

根据首次适应算法,我们将在第一个满足条件的空闲分区进行分配。

在这种情况下,我们将分配200字节的空闲分区和分配400字节的空闲分区拆分为600字节的已分配分区和空闲分区。

最后,假设一个进程请求200字节的内存空间。

根据首次适应算法,我们在第一个满足条件的空闲分区进行分配。

在这种情况下,我们将250字节的空闲分区拆分为200字节的已分配分区和50字节的空闲分区。

动态分区分配方式的模拟实验报告

动态分区分配方式的模拟实验报告
{
if(L[i].rom-T[k].rom>Size)
{
L[i].sad=L[i].sad+T[k].rom;
L[i].rom=L[i].rom-T[k].rom;
L[i].state=1;
T[k].sad=L[i].sad-T[k].rom;
printf("内存分配成功!\n作业申请空间为%d\n起始地址为%d\n",T[k].rom,T[k].sad);
2. 给出初始状态、可用内存空间、请求序列,分别采用首次适应算法和最佳适应算法进行内存块的分配和回收,要求每次分配和回后显示出空闲内存分区链的情况(共有多个空闲分区,每个空闲分区的大小分别为多大)。
4.实验原理或流程图
首次适应算法(First-fit):当要分配内存空间时,就查表,在各空闲区中查找满足大小要求的可用块。只要找到第一个足以满足要球的空闲块就停止查找,并把它分配出去;如果该空闲空间与所需空间大小一样,则从空闲表中取消该项;如果还有剩余,则余下的部分仍留在空闲表中,但应修改分区大小和分区始址。
{
printf("请输入第%d个分区的信息:\n",i);
cin>>L[i].rom>>L[i].sad;
L[i].id=i;
L[i].state=0;
}
printf("输入完毕,当前空闲分区表状态为:\n");
print();
printf("请输入不再切割的剩余空间的大小:\n");
cin>>Size;
{
int id;///空闲分区编号
int sad;///空闲分区首地址
int rom;///空间

计算机操作系统实验报告动态分区分配方式的模拟

计算机操作系统实验报告动态分区分配方式的模拟

计算机操作系统实验报告姓名:班级:学号:题目:动态分区分配方式的模拟实习内容简要描述本次实验要完成两部分内容:一是用C语言实现对采用首次适应算法和最佳适应算法的动态分区分配过程ALLOCo和回收过程FREE(),其中空闲分区由空闲分区链来管理,进行分配时,系统优先使用空闲区底端空间。

二是假设初始状态下,可用内存空间为640KBO按照题目要求的作业顺序,以及各个作业分配和回收的内存空间。

分别采用首次适应法和最佳适应法,对内存进行分配和回收,要求每次分配和回收后显示空闲内存分区链的情况。

实验分析算法介绍本次实验通过用C语言进行编程并调试、运行,形象地表现出动态分区的分配方式,直观地展现了首次适应算法和最佳适应算法对内存的释放和回收方式之间的区别。

加深了我们对两种算法优缺点的理解,帮助我们了解一些数据结构和分配算法,进一步加深我们对动态分区存储器管理方式及其实现过程的理解。

主要的问题在于,如何解决两种算法对内存的释放和回收空间的表示。

动态分区分配:又称为可变分区分配,这种分配方式并不事先先将主存划分成一块块的分区,而是在作业进入主存时,根据作业的大小动态地建立分区。

并使分区的大小正好适应作业的需要。

因此系统中分区的大小是可变的,分区的数目也是可变的。

分区分配算法:(两者的空闲块链接方式不冋)①首次适应法:为作业选择分区时总是按地址从高到低搜索,只要找到可以容纳该作业的空白块,就把该空白块分配给该作业。

特点:优先利用内存中底地址部分的空闲分区(将所有空闲区,按其地址递增的顺序链接)②最佳适应算法:接到内存申请时,在空闲块表中找到一个不小于请求的最小空块进行分配;为作业选择分区时总是寻找其大小最接近于作业所要求的存储区域。

特点:用最小空间满足要求(将所有空闲区,按其大小递增的顺序联接成空闲区链)结果分析(思考题解答;错误原因分析)间的分配和回收。

思考题解答:1、首次适应算法分配时从表头指针开始查找可利用空间表,将找到的第一个大小不小于“请求”的空闲块的一部分分配给用户。

动态分区分配方式模拟

动态分区分配方式模拟

动态分区分配方式模拟动态分区分配方式的核心思想是将内存划分为若干个不同大小的分区,每个分区可以用来存放一个进程或作为一部分进程的存储区域。

当一个进程需要分配内存时,系统会根据进程的需要选择一个合适大小的空闲分区分配给该进程。

当进程执行完毕后,系统会回收其占用的内存分区,再次将其标记为空闲分区。

首次适应算法(First Fit)是最简单的动态分区分配算法之一、它从内存的起始位置开始,寻找第一个满足进程需要的空闲分区,然后将该分区分配给进程。

首次适应算法的优点是实现简单,且内存利用率较高。

然而,它也有一些缺点,比如容易产生碎片,导致内存的利用率下降。

最佳适应算法(Best Fit)是根据进程需要的内存大小,选择最小的满足条件的空闲分区进行分配。

最佳适应算法可以最大限度地减少碎片的产生,提高内存的利用率。

但是,最佳适应算法的缺点是实现较为复杂,同时由于选择最小的分区进行分配,会导致大量的碎片出现。

最坏适应算法(Worst Fit)与最佳适应算法相反,它选择最大的满足进程需要的空闲分区进行分配。

最坏适应算法的优点是可以减少大型进程的外部碎片,但由于选择最大的分区进行分配,会导致更多的碎片产生。

为了更好地理解动态分区分配方式,我们可以通过一个简单的模拟实例来进行说明。

假设有一块内存大小为1MB,现有以下三个请求需要进行内存分配:1.进程A需要200KB的内存;2.进程B需要400KB的内存;3.进程C需要600KB的内存。

首次适应算法:首先,进程A需要200KB的内存,首次适应算法从内存起始位置开始寻找空闲分区,找到一个大小符合要求的空闲分区,将其分配给进程A。

然后,进程B需要400KB的内存,首次适应算法会从上次分配的位置开始,找到一个大小满足要求的空闲分区,并将其分配给进程B。

最后,进程C需要600KB的内存,首次适应算法会继续从上次分配的位置开始,但发现没有足够的空闲分区,分配失败。

最佳适应算法:最佳适应算法需要对所有空闲分区进行排序,按照分区大小的升序排列。

(完整word版)动态分区分配方式模拟

(完整word版)动态分区分配方式模拟

使用动态分区分配方式的模拟1内容(1)用C语言分别实现采用首次适应算法和最佳适应算法的动态分区分配过程alloc( )和回收过程free( )。

其中,空闲分区通过空闲分区链来管理:在进行内存分配时,系统优先使用空闲区低端的空间。

(2)假设初始状态下,可用的内存空间为640KB,并有下列的请求序列:•作业1申请130KB。

•作业2申请60KB。

•作业3申请100KB。

•作业2释放60KB。

•作业4申请200KB。

•作业3释放100KB。

•作业1释放130KB。

•作业5申请140KB。

•作业6申请60KB。

•作业7申请50KB。

•作业6释放60KB。

请分别采用首次适应算法和最佳适应算法,对内存块进行分配和回收,要求每次分配和回收后显示出空闲分区链的情况。

2、示例程序://Tittle: 使用动态分区算法的模拟//author: XuYongzhen#include <stdio.h>#include <stdlib.h>#include <malloc.h>#include <iostream>using namespace std;typedef struct DuLNode{struct DuLNode *prior;struct DuLNode *next;int address;int jsize;int jnumber;//显示分区被那个作业占用,显示零则为空闲分区;}DuLNode,*DuLinkList ;void CreatList(DuLinkList &L){DuLinkList p=(DuLinkList)malloc(sizeof(DuLNode));L->next=p;L->jnumber=100;//为释放头结点后面的结点空间做统一化处理p->prior=L;p->next=NULL;p->jsize=600;p->address=0;p->jnumber=0;}void RequestList(DuLinkList &L,int job,int size){cout<<"作业"<<job<<"申请"<<size<<"KB的空间"<<endl;DuLinkList p=L->next;while((p->jnumber>0||p->jsize<size)&&p)p=p->next;if(p==NULL)cout<<"没有适合的空间分配"<<endl;else{DuLinkList s=(DuLinkList)malloc(sizeof(DuLNode));s->prior=p->prior;p->prior->next=s;s->next=p;p->prior=s;s->jnumber=job;s->jsize=size;s->address=p->address;p->address=p->address+s->jsize;p->jsize=p->jsize-s->jsize;DuLinkList t=L->next;while(t){if(t->jnumber==0)cout<<"空闲分区:始址="<<t->address<<"大小="<<t->jsize<<endl;elsecout<<"已分配的分区:作业号="<<t->jnumber<<"始址="<<t->address<<"大小="<<t->jsize<<endl;t=t->next;}//whilecout<<endl;}//else}//RequestListvoid FreeList(DuLinkList &L,int job){cout<<"作业"<<job<<"释放"<<endl;DuLinkList p=L->next;while(p->next&&p->jnumber!=job)p=p->next;if(p->prior->jnumber==0 && p->next->jnumber==0){//p的前后都是空闲分区,则合并三者DuLinkList s=p->next;DuLinkList q=p->prior;p->prior->next=p->next;p->next->prior=p->prior;s->prior->next=s->next;s->next->prior=p->prior;q->jsize=p->jsize+s->jsize+q->jsize;}if(p->prior->jnumber==0 && p->next->jnumber!=0){//回收区与插入点的前一个分区相临接DuLinkList q=p->prior;p->prior->next=p->next;p->next->prior=p->prior;q->jsize=p->jsize+q->jsize;}if(p->prior->jnumber!=0 && p->next->jnumber==0){//回收区与插入点的后一个分区相临接DuLinkList q=p->next;p->prior->next=p->next;p->next->prior=p->prior;q->address=p->address;q->jsize=p->jsize+q->jsize;}if(p->prior->jnumber!=0 && p->next->jnumber!=0)//回收区去插入点前后的两个空闲分区都不相临接p->jnumber=0;DuLinkList t=L->next;while(t){if(t->jnumber==0)cout<<"空闲分区:始址="<<t->address<<"大小="<<t->jsize<<endl;elsecout<<"已分配的分区:作业号="<<t->jnumber<<"始址="<<t->address<<"大小="<<t->jsize<<endl;t=t->next;}cout<<endl;}void main(){DuLinkList L=(DuLinkList)malloc(sizeof(DuLNode));CreatList(L);RequestList(L,1,130);RequestList(L,2,60);RequestList(L,3,100);FreeList(L,2);RequestList(L,4,200);FreeList(L,3);FreeList(L,1);RequestList(L,5,140);RequestList(L,6,60);RequestList(L,7,50);FreeList(L,6);}。

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

课程设计报告课程设计题目:循环首次适应的动态分区分配算法模拟专业:计算机科学与技术班级:10204102姓名:谱学号: 10204102指导教师:高小辉2013年1月11 日目录一.循环首次适应算法 (3)1. 概述 (3)2.需求分析 (3)二.实验指导 (4)1.基本思想 (4)2.数据结构 (4)三.运行环境 (6)四.流程图 (6)五.循环首次适应算法代码 (5)六.调试结果 (11)七、总结 (14)八.参考文献 (14)一.循环首次适应算法1.概述:该算法是由首次适应算法演变而成的。

在为进程分配内存空间时,不再是每次都从链首开始查找,而是从上次找到的空闲分区的下一个空闲分区开始查找,直至找到一个能满足要求的空闲分区,从中划出一块的请求大小相等的内存空间分配给作业。

为实现该算法,应设置一起始查找指针,用于指示下一次起始查询的空闲分区,并采用循环查找方式,即如果最后一个(链尾)空闲分区的大小仍不能满足要求,则返回到第一个空闲分区,比较大小是否满足,找到后,应调整起始查询指针。

2. 需求分析了解动态分区分配中使用的数据结构和分配算法,并进一步加深对动态分区存储管理方式及其实现过程的理解。

采用首次适应算法的动态分区分配过程alloc()和回收过程free()。

空闲分区通过空闲分区链表来管理,在进行内存分配时,系统优先使用空闲区低端的空间,即每次分配内存空间是总是从低址部分开始进行循环,找到第一个合适的空间,便按作业所需分配的大小分配给作业。

作业完成时,需要释放作业所占空间,此时要考虑到四种情况:(1)回收区与插入点的前一个空闲分区相邻接。

此时将二者合并,修改前一分区的大小。

(2)回收区与插入点的后一空闲分区相邻接,将二者合并,用回收区的首址作为新空闲区的首址。

(3)回收区同时与插入点的前后两个空闲分区相邻接,三者合并,使用前一空闲分区的表项和首址。

(4)回收区单独存在。

二、实验指导1.基本思想动态分区是指系统不预先划分固定分区,而是在装入程序的时候划分内存区域,使得为程序分配的分区大小恰好等于该程序的需求量,且分区的个数是动态的。

显然动态分区有较大的灵活性,较之固定分区能获得好的内存利用率。

2.数据结构动态分区管理可以用两种数据结构实现,一种是已分配区表和空闲区表,也就是用预先定义好的系统空间来存放空间分配信息。

另一种也是最常用的就是空闲链表,由于对分区的操作是动态的,所以很难估计数据结构所占用的空间,而且空闲区表会占用宝贵的系统空间,所以提出了空闲链表的概念。

其特点是用于管理分区的信息动态生成并和该分区在物理地址上相邻。

这样由于可以简单用两个空闲块之间的距离定位已分配空间,不仅节约了系统空间,而且不必维持已分配空间的信息。

本实验是要做一个模拟程序,来模拟动态分区算法的分配和回收过程,并不是真正的去分配和回收内存。

基本的模拟方法有两种:1、先从内存中申请一块存储区,对这块存储区进行模拟的分配和回收活动。

2、不申请存储区,自己定义一块虚拟的存储区,对这块存储区进行模拟的分配和回收活动,分配和回收仅仅是对数据结构的修改而已。

三.运行环境:1.操作系统 WINDOWS XP2.编译软件 Microsoft Visual C++3.电脑配置:主频3.0GHz 内存512MB四.流程图1.程序结构如图:2.首次适应算法的结构如图:五.循环首次适应算法代码#include <iostream>#include <stdlib.h>#include <stdio.h>using namespace std;struct memory{struct memory *former; //前向指针 int address;//地址int num;//作业号int size;//分配内存大小int state;//状态0表示空闲1表示已分配struct memory *next; //后向指针};typedef struct memory MEMORY;MEMORY *mem;const int size_min=10;//内存允许的最小空闲块的大小void init(); //初始化内存块void exec();//执行相应算法void F_F(int); //依次初始化每个作业,并根据相应算法对作业分配内存void alloc(MEMORY *,MEMORY *);//分配内存算法(包括两种不同算法)void free(MEMORY *,int);//首次适应算法回收内存void sort(MEMORY *);//对内存链进行排序void insert(MEMORY *,MEMORY *); //按空间大小将作业顺序插入到内存链void print(MEMORY *);//打印内存链void main(){ //主函数int i=0;while(1){ //选择算法cout<<("\n欢迎进入!");cout<<("\nPlease select a number(1,0)");cout<<("\n 循环首次适应算法");cout<<" 0--中止程序"<<endl;cin>>i;if(i==1){ //首次适应算法cout<<("\n以下为首次适应算法:\n");init();exec();}elseexit(1);}}void init(){ //初始化内存容量mem=new MEMORY;mem->size=640;mem->former=0;mem->next=0;}void exec(){//执行算法while(1){//选择申请或释放内存操作cout<<"**************************"<<endl;cout<<"申请内存请输入作业号(1-6)"<<endl;cout<<"释放内存请输入数字8"<<endl;cout<<"中止程序请输入数字0"<<endl;cout<<"**************************"<<endl;int k;cin>>k;//根据k值选择相应的操作if(k>=1&&k<=7) F_F(k);if(k==8){int m;cout<<"请输入要释放的作业号:";cin>>m; //选择相应的回收算法free(mem,m);}else if(k==0){//回滚到选择算法的步骤break;}}}void F_F(int i){ //依次初始化每个作业,并根据相应算法对作业分配内存int work[]={130,60,100,200,160,60,50};//作业序列,i从1开始(与作业号对应),因此从第一个开始存放作业值,第0个值为0,不是作业cout<<"请输入要作业所需的内存大小:";MEMORY *running;running=(MEMORY *)malloc(sizeof(MEMORY));if(running!=NULL){ running->former=NULL;running->address=0;running->num=i; //i从1开始循环running->size=work[i]; //指定作业大小running->state=0; //作业未分配running->next=NULL;//根据相应算法为作业分配内存,详见alloc函数alloc(mem,running); print(mem); cout<<endl;}elsecout<<"没有足够的内存空间"<<endl;}void print(MEMORY *ptr){ //打印显示内存情况MEMORY *temp;temp=ptr->next;cout<<"\n内存链的状态为:"<<endl;while(temp!=NULL){if(temp->state==0){cout<<"内存空闲 "<<"起始地址为:"<<temp->address<<" 空闲空间大小为:"<<temp->size<<"k";}else{cout<<"内存已分配 "<<"起始地址为:"<<temp->address<<" 分配空间大小为:"<<temp->size<<"k" <<" 运行的作业号:"<<temp->num;}cout<<endl;temp=temp->next;}}void free(MEMORY *ptr,int i){ //首次适应算法作业处理完后释放内存空间MEMORY *previous,*current;previous=ptr; current=previous->next;while(current!=NULL){ //循环直到找到需要释放的作业位置if(current->state==1&&current->num==i){ break;}previous=current;current=current->next;}if(current==NULL){ cout<<"内存中没有任何作业!!!"<<endl; return; }else if(current->next==NULL){ //当前作业为内存中最后一个作业if(previous->state==0){ //与前一个相邻空闲区合并previous->size=previous->size+current->size;previous->next=NULL;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //将状态改为0,即为空闲区current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}else if((current->next)->next==NULL)//p6{ //当前作业为倒数第二个作业(此种情况还是要单列出来讨论的否则会出现错误)if(previous->state==0&&(current->next)->state==0) //p7 { //释放的地址空间前后均为空闲区previous->size=previous->size+current->size+(current->next)->size; previous->next=NULL; //与下边else(其他情况的不同之处)cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if(previous->state==0) //p5{ //释放的地址空间前面有空闲块则把它和前面的合并previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if((current->next)->state==0) //p8{ //释放的地址空间后面有空闲块则把它和后面的空闲块合并current->size=current->size+(current->next)->size;current->state=0;current->next=NULL; //与下边else(其他情况的不同之处)cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //释放的地址空间前后都没有空闲块时直接把它的状态改为0current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}else{ //其他情况下(当前作业在链表中间)if(previous->state==0&&(current->next)->state==0) //p7 { //所释放空间前后均为空闲区previous->size=previous->size+current->size+(current->next)->size; ((current->next)->next)->former=previous;previous->next=(current->next)->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if(previous->state==0) //p5{ //释放的地址空间前面有空闲块则把它和前面的合并previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else if((current->next)->state==0) //p8{ //释放的地址空间后面有空闲块则把它和后面的空闲块合并current->size=current->size+(current->next)->size;current->state=0;((current->next)->next)->former=current;current->next=(current->next)->next;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}else{ //处理完的作业前后都没有空闲块时直接把它的状态改为0current->state=0;cout<<"作业 "<<(current->num)<<"释放 "<<(current->size)<<"k 的空间"<<endl;print(mem);}}}void alloc(MEMORY *ptr,MEMORY *assign){ //根据算法分配内存(is_optimist状态)if(ptr->next==NULL){ //内存没有作业运行if(ptr->size>=assign->size){ //内存空间大于作业所需空间,为内存分配空间ptr->size=ptr->size-assign->size;assign->state=1;ptr->next=assign;assign->former=ptr;cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}else{cout<<"没有足够的内存空间为作业"<<(assign->num)<<"分配"<<endl; delete assign;}}else{ //内存中如果已经分配了空间MEMORY *previous,*current;previous=ptr;//previous为链表中的第一个元素current=previous->next;while(current!=NULL){//当前区间不为空(最后一个区间的next为空),即没有循环到最后//如果当前内存空间大于作业所需空间并且内存没有被分配//则结束循环,当前current位置即为要插入的位置if(current->size>=assign->size&&current->state==0){break;}previous=current; //previous后移current=current->next;}if(current==NULL){ //空闲链中没有为作业分配所需的空间,即释放的空闲区间小于要分配的作业空间//不够用,则在所有作业后边另外再申请空闲区,如作业4if(ptr->size>=assign->size){ //内存中还有足够没分配的空闲空间为此作业分配//此时ptr指向内存上未分配空闲空间的起始地址assign->address =640-(ptr->size);ptr->size=ptr->size-assign->size;assign->state=1;assign->former=previous;previous->next=assign;cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}else{cout<<"没有足够的内存空间为作业"<<(assign->num)<<"分配"<<endl;}}else{ //释放的空闲链中有可为此作业分配的空间if((current->size-assign->size)<=size_min){ //空闲链所具备的空间与作业所需空间大小差不多时//直接把整个空闲块的空间分配给作业否则从空闲块中current->num=assign->num; //划出与作业等同的空间current->state=1;delete assign;cout<<"作业 "<<(current->num)<<"申请"<<(current->size)<<" "<<"k 的内存间"<<endl;}else{ //从空闲块中划分一块与作业大小等同的空间current->size=current->size-assign->size;assign->state=1;assign->address=current->address+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;}cout<<"作业 "<<(assign->num)<<"申请"<<(assign->size)<<" "<<"k的内存空间"<<endl;}}}}六.调试结果1输入条件作业1申请130KB;作业2申请60KB;作业3申请100KB;作业2释放60KB;作业4申请200 KB;作业3释放100 KB;作业1释放130 KB;作业5申请140 KB;作业6申请60 KB;作业7申请50KB;作业6释放60 KB2运行结果:七.总结本次操作系统课程设计让我掌握了动态分区分配的实质:动态分区分配是根据进程的实际需要,动态地为之分配内存空间。

相关文档
最新文档