实验四 内存管理模拟实验
实验4虚拟内存管理实验

实验4虚拟内存管理实验实验4 虚拟内存管理实验一、实验目的1. 掌握虚拟存储器的实现方法2. 掌握各种页面置换算法3. 比较各种页面置换算法的优缺点二、实验内容三、实验结果1. 程序源代码:Main.cpp#include <iostream> #include <string> #include <vector> #include <cstdlib> #include <cstdio> #include </unistd.h> </cstdio> </cstdlib> </vector> </string> </iostream>using namespace std;#define ***** -1const int TOTAL_*****TION(320); const int TOTAL_VP(32);#include \#include \#include \int main() {int i;CMemory a; for(i=4;ii++) {a.FIFO(i); a.LRU(i); // a.NUR(i); // a.OPT(i); cout \}return 0; }Memory.h#ifndef _MEMORY_H// 总共使用页面次数320次// 内存分配的页面数32个#define _MEMORY_Hclass CMemory {public:CMemory(); void initialize(const int nTotal_pf); void FIFO(const int nTotal_pf); void LRU(const int nTotal_pf); 面个数// void NUR(const int nTotal_pf); // void OPT(const int nTotal_pf); private:// 构造函数// 初始化函数// LRU算法,参数表示分配的内存页vector<cpage> _vDiscPages; </cpage>该进程空间内的所有页vector<cpagecontrol> _vMemoryPages; 页向量</cpagecontrol>CPageControl *_pFreepf_head; 于LRU算法CPageControl *_pBusypf_head,*_pBusypf_tail; 指针,用于FIFO算法vector<int> _vMain,_vPage; 产生的指令序列</int>// _vPage表示待处理指令对应的页号int _nDiseffect;// 进程使用的页向量,包含// 为进程分配的物理内存// 空闲物理页头指针,用// 已使用页面头指针,尾// _vMain表示某进程随机// 换入页面次数};CMemory::CMemory():_vDiscPages(TOTAL_VP), // 32 _vMemoryPages(TOTAL_VP), // 32 _vMain(TOTAL_*****TION), // 320 _vPage(TOTAL_*****TION) {int S,i,nRand;// 通过随机数产生一个指令序列(实际上是指令的逻辑地址序列),共320条指令。
内存管理实验报告

内存管理实验报告内存管理实验报告引言内存管理是计算机系统中非常重要的一部分,它负责管理计算机系统的内存资源,为程序的运行提供必要的支持。
本次实验旨在探究不同的内存管理策略对计算机系统性能的影响,以及如何优化内存管理以提高系统效率。
一、实验背景计算机系统中的内存是用于存储程序和数据的关键资源。
在多道程序设计环境下,多个程序需要共享有限的内存资源,因此需要一种有效的内存管理策略来分配和回收内存空间。
本次实验中,我们将研究并比较两种常见的内存管理策略:固定分区和动态分区。
二、实验过程1. 固定分区固定分区是将内存划分为固定大小的若干区域,每个区域可以容纳一个程序。
在实验中,我们将内存划分为三个固定大小的区域,并将三个不同大小的程序加载到内存中进行测试。
通过观察程序的运行情况和内存利用率,我们可以评估固定分区策略的优缺点。
2. 动态分区动态分区是根据程序的大小动态地分配内存空间。
在实验中,我们将使用首次适应算法来实现动态分区。
首次适应算法将按照程序的大小从低地址开始查找可以容纳该程序的空闲分区,并分配给程序使用。
通过观察动态分区策略下的内存利用率和碎片情况,我们可以评估该策略的优劣。
三、实验结果1. 固定分区在固定分区策略下,我们观察到每个程序都能够顺利运行,但是内存利用率较低。
由于每个程序都需要占用一个固定大小的分区,当程序大小与分区大小不匹配时,会出现内存浪费的情况。
此外,固定分区策略也存在无法分配较大程序的问题。
2. 动态分区在动态分区策略下,我们观察到内存利用率较高,碎片情况也较少。
由于动态分区可以根据程序的大小动态分配内存空间,因此可以更加高效地利用内存资源。
然而,动态分区策略也存在着内存分配和回收的开销较大的问题。
四、实验总结通过本次实验,我们对固定分区和动态分区两种内存管理策略进行了比较和评估。
固定分区策略适用于程序大小已知且固定的情况,但会导致内存浪费;而动态分区策略可以更加灵活地分配内存空间,但会增加内存分配和回收的开销。
内存管理实验报告

内存管理实验报告实验名称:内存管理实验目的:掌握内存管理的相关概念和算法加深对内存管理的理解实验原理:内存管理是操作系统中的一个重要模块,负责分配和回收系统的内存资源。
内存管理的目的是高效地利用系统内存,提高系统的性能和稳定性。
实验过程:1.实验环境准备本实验使用C语言编程,要求安装GCC编译器和Linux操作系统。
2.实验内容实验主要包括以下几个部分:a.基本内存管理创建一个进程结构体,并为其分配一定大小的内存空间。
可以通过C语言中的指针操作来模拟内存管理的过程。
b.连续分配内存算法实现两种连续分配内存的算法:首次适应算法和最佳适应算法。
首次适应算法是从低地址开始寻找满足要求的空闲块,最佳适应算法是从所有空闲块中选择最小的满足要求的块。
c.非连续分配内存算法实现分页和分段两种非连续分配内存的算法。
分页是将进程的虚拟地址空间划分为固定大小的页面,然后将页面映射到物理内存中。
分段是将进程的地址空间划分为若干个段,每个段可以是可变大小的。
3.实验结果分析使用实验中的算法和方法,可以实现对系统内存的高效管理。
通过比较不同算法的性能指标,我们可以选择合适的算法来满足系统的需求。
具体而言,连续分配内存算法中,首次适应算法适用于内存中有大量小碎片的情况,可以快速找到满足要求的空闲块。
最佳适应算法适用于内存中碎片较少的情况,可以保证最小的内存浪费。
非连续分配内存算法中,分页算法适用于对内存空间的快速分配和回收,但会带来一定的页表管理开销。
分段算法适用于对进程的地址空间进行分段管理,可以灵活地控制不同段的权限和大小。
实验中还可以通过性能测试和实际应用场景的模拟来评估算法的性能和适用性。
实验总结:本实验主要介绍了内存管理的相关概念和算法,通过编写相应的代码实现了基本内存管理和连续分配、非连续分配内存的算法。
通过实际的实验操作,加深了对内存管理的理解。
在实验过程中,我们发现不同算法适用于不同情况下的内存管理。
连续分配算法可以根据实际情况选择首次适应算法或最佳适应算法。
操作系统实验四存储管理实验(1)

操作系统课程实验年级2012 级专业计算机科学与技术(应用型)姓名学号指导教师日期实验四、存储管理实验一、关键问题1、实验目的理解内存分配和回收原理。
2、实验环境Ubuntu 8.0或者以上,Eclipse集成开发环境3、实验内容3.1 在控制台内观察Linux内存分配情况3.2存储管理模拟实验要求:写一动态分区管理程序,使其内存分配采用最佳适应分配算法。
老师所给的例子为内存分配算法是最先适应分配算法的系统模拟动态分区管理方案,而问题的关键就是如何把最先适应分配算法改为最佳适应分配算法。
二、设计修改思路struct freearea* min1=NULL;//定义了一个符合条件的最小空白块链表首先我们在分配内存函数中需要定义一个记录符合条件的最小空白块的链表结构指针,对当前空闲分区链进行遍历,找到符合条件的最小空白块并记录。
系统为作业分配内存时,根据指针freep查找空闲分区链。
当找到一块可以满足请求中最小的空闲分区时便分配。
当空间被分配后剩余的空间大于规定的碎片,则形成一个较小的空闲分区留在空闲链中。
三、实现修改的关键代码//有两个链:空白块链及作业链.空白块链描述空白块,链首指针freep,初始为一大块空白块.//作业链按从高址到低址的顺序链接,链首指针jobp//为作业jn分配jl大小内存,起始地址为javoid ffallocation(int jl,char jn[10],int* ja){struct mat* jp=NULL;//作业链当前节点struct mat* jp2=NULL;//新的作业节点struct mat* jp1=NULL;//struct freearea* fp=NULL;//当前空白块struct freearea* min1=NULL;//定义了一个符合条件的最小空白块链表int flag=0;int i;*ja=-1;if (totalfree<jl) //剩余空间大小不能满足作业要求return;fp=freep;while (fp!=NULL){if (fp->freesize>jl){ min1=fp;flag=1;break;}fp=fp->next;}if(freep->next!=NULL&&flag==0) {*ja=0;return;}fp=min1->next;while (fp!=NULL){if (fp->freesize>jl&&fp->freesize<min1->freesize)min1=fp;fp=fp->next;//当前空白块大小不满足要求}jobnumber++;totalfree=totalfree-jl;jp2=calloc(1,sizeof(struct mat));//在节点上登记为该作业分配的内存空间// for (i=0;i<10;i++) (jp2->jobname)[i]=' ';i=-1;while(jn[++i])(jp2->jobname)[i]=jn[i];(jp2->jobname)[i]='\0';jp2->joblength=jl;jp2->jobaddress=min1->freeaddress;//登记该作业的起始地址(块的最低地址)*ja=jp2->jobaddress;//将节点jp2插入作业链jobp,按高址到低址的顺序。
实验四 操作系统存储管理实验报告

实验四操作系统存储管理实验报告一、实验目的本次操作系统存储管理实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配、回收、地址转换等关键技术,提高对操作系统存储管理机制的认识和应用能力。
二、实验环境操作系统:Windows 10开发工具:Visual Studio 2019三、实验原理1、内存分配方式连续分配:分为单一连续分配和分区式分配(固定分区和动态分区)。
离散分配:分页存储管理、分段存储管理、段页式存储管理。
2、内存回收算法首次适应算法:从内存低地址开始查找,找到第一个满足要求的空闲分区进行分配。
最佳适应算法:选择大小最接近作业需求的空闲分区进行分配。
最坏适应算法:选择最大的空闲分区进行分配。
3、地址转换逻辑地址到物理地址的转换:在分页存储管理中,通过页表实现;在分段存储管理中,通过段表实现。
四、实验内容及步骤1、连续内存分配实验设计一个简单的内存分配程序,模拟固定分区和动态分区两种分配方式。
输入作业的大小和请求分配的分区类型,程序输出分配的结果(成功或失败)以及分配后的内存状态。
2、内存回收实验在上述连续内存分配实验的基础上,添加内存回收功能。
输入要回收的作业号,程序执行回收操作,并输出回收后的内存状态。
3、离散内存分配实验实现分页存储管理的地址转换功能。
输入逻辑地址,程序计算并输出对应的物理地址。
4、存储管理算法比较实验分别使用首次适应算法、最佳适应算法和最坏适应算法进行内存分配和回收操作。
记录不同算法在不同作业序列下的内存利用率和分配时间,比较它们的性能。
五、实验结果与分析1、连续内存分配实验结果固定分区分配方式:在固定分区大小的情况下,对于作业大小小于或等于分区大小的请求能够成功分配,否则分配失败。
内存状态显示清晰,分区的使用和空闲情况一目了然。
动态分区分配方式:能够根据作业的大小动态地分配内存,但容易产生内存碎片。
2、内存回收实验结果成功回收指定作业占用的内存空间,内存状态得到及时更新,空闲分区得到合并,提高了内存的利用率。
内存管理实验

内存管理实验实验目的:用高级语言编写和调试一个内存管理程序,以加深对内存的分配、回收以及空闲块管理的理解。
实验内容:编写一个模拟程序,完成内存可变分区分配的模拟,要求采用最佳适应法、最坏适应法、首次适应法或下次适应法之一。
实验具体包括:首先确定分配内存块管理的数据结构、空闲块的数据结构,然后完成内存分配、内存回收、空闲块管理等程序代码;最后编写模拟分配和回收过程的主函数,上机实验并取得结果数据。
程序流程图:结果及分析:给出至少两组模拟的输入和输出结果数据(包括已分配情况、空闲块情况),分析算法的模拟情况,以及自己的收获。
<一>.第一组数据:输入: 初始化内存空间大小内存首址作业大小作业名称100 1 35 1 输出: ------------已分配表-----------分区号始地址作业名称作业大小状态1 1 1 35 1------------空闲表--------------分区号始地址剩余大小状态2 36 65 0<二>.第二组数据:输入: 作业名称作业大小220输出: -------------已分配表------------分区号始地址作业名称作业大小状态1 1 1 35 12 36 2 20 1--------------空闲表--------------分区号始地址剩余大小状态2 56 45 0源程序:源程序包括两部分:<一>.头文件://-----------------------------------------------------------------// //结构体定义//存储资源表结构(已分区表)typedef struct LNode {int address; //首地址int size; //内存分区大小int state; //状态:0表示空闲,1表示已经装入作业int num; //装入的作业号LNode *Next;}LNode,*mem_list;//-----------------------------------------------------------------////-----------------------------------------------------------------// //函数申明void Init(mem_list &L,int size,int add); //初始化空间段void setfree(mem_list &L);//找出连续的空闲资源,回收空闲空间void AddTask(mem_list &L);//添加作业void Display(mem_list L);//显示作业//-----------------------------------------------------------------////-----------------------------------------------------------------// //函数定义//初始化空间段void Init(mem_list &L,int size,int add) {mem_list p =(mem_list)malloc(sizeof(LNode));p->address = add;p->size = size;p->state = 0;p->num = 0;p->Next = NULL;L->Next = p;}//找出连续的空闲资源,回收空闲空间void setfree(mem_list &L) {mem_list p=L->Next,q = p->Next;while(p && q) {if(p->state == 0 && q->state == 0) {//如果空间连续,则回收p->size += q->size;p->Next = p->Next->Next;delete q;q=p->Next;}else{p = q;q = q->Next;}}printf("回收成功\n");}//添加作业void AddTask(mem_list &L) {int new_size;int new_name;mem_list p = L->Next, best = NULL;printf("请输入作业名称(用数字表示):");scanf("%d",&new_name);printf("请输入作业的大小:");scanf("%d",&new_size);printf("\n\n");if (new_size<=0) {printf("申请失败\n");exit(-1);}while(p) {//查找第一个满足空间分配的节点if(p->state==0 && p->size >= new_size) {best=p;break;}p=p->Next;}if(!p) {printf("对不起,作业%d内存分配不成功\n",new_name);exit(1);}p=L;while(p) {//查找最佳适应节点if(p->state==0 && p->size >= new_size && best->size > p->size) best = p;p = p->Next;}mem_list q =(mem_list)malloc(sizeof(LNode));q->size = best->size - new_size;q->address = best->address + new_size;q->state = 0;q->num=0;best->size = new_size;best->state = 1;best->num = new_name;q->Next = best->Next;best->Next = q;p=L;while(p) {//删除大小为0的结点,当分配空间完时会出现0结点if(p->size == 0) {q->Next = q->Next->Next;delete p;p = q->Next;}else {q = p;p = p->Next;}}}//显示作业void Display(mem_list L) {int count=1;mem_list p = L->Next;printf("----------已分配表----------\n");printf("分区号始地址作业长度状态\n");while(p) {if(p->num) {if(p->state)p->state=1;elsep->state=0;printf("%3d%8d%8d%8d%8d\n",count++,p->address,p->num,p->size,p->s tate);}p = p->Next;}p = L->Next;count = 1;printf("\n\n----------空闲表----------\n");printf("分区号始地址长度状态\n");while(p) {if(!(p->num)) {if(p->state)p->state=1;elsep->state=0;printf("%3d%8d%8d%8d\n\n",++count,p->address,p->size,p->state);}p = p->Next;}}//-----------------------------------------------------------------//<二>.主文件:#include <stdio.h>#include <iostream>#include <stdlib.h>#include <malloc.h>#include "work2.h"void main() {mem_list L=(mem_list)malloc(sizeof(LNode)); //申请节点空间int N,A;char flag;printf("------------------内存管理程序----------------\n");printf(" ********************\n");printf(" * 姓名:阳功力 *\n");printf(" * 学号:052413 *\n");printf(" * 班级: 9452 *\n");printf(" ********************\n\n"); printf("请初始化空间的大小:");scanf("%d",&N);printf("内存首址:");scanf("%d",&A);Init(L,N,A); //初始化大小为N,首址为A的内存空间do {AddTask(L); //添加作业Display(L); //显示作业printf("请选择是否继续添加作业(继续请按'y',否则回收空间结束)...:");scanf("%s",&flag);}while(flag == 'y');setfree(L);}。
操作系统内存管理实验报告

#include <stdio.h>
#include <malloc.h>
t;
int main(void)
{
char *str; /*为字符串申请分配一块内存*/
if ((str = (char *) malloc(10)) == NULL)
根据练习二改编程序如下:
#include <stdio.h>
#include <malloc.h>
#include <string.h>
int main(void)
{
char *str;
/*为字符串申请分配一块内存*/
if ((str = (char *) malloc(20)) == NULL)
{
同组同学学号:
同组同学姓名:
实验日期:交报告日期:
实验(No. 4)题目:编程与调试:内存管理
实验目的及要求:
实验目的:
操作系统的发展使得系统完成了大部分的内存管理工作,对于程序员而言,这些内存管
理的过程是完全透明不可见的。因此,程序员开发时从不关心系统如何为自己分配内存,
而且永远认为系统可以分配给程序所需的内存。在程序开发时,程序员真正需要做的就
printf("String is %s\n Address is %p\n", str, str);
/*重分配刚才申请到的内存空间,申请增大一倍*/
int main(void)
{
char *str;
/*为字符串申请分配一块内存*/
if ((str = (char *) malloc(10)) == NULL)
操作系统实验-内存管理

操作系统实验-内存管理操作系统实验内存管理在计算机系统中,内存管理是操作系统的核心任务之一。
它负责有效地分配和管理计算机内存资源,以满足各种程序和进程的需求。
通过本次操作系统实验,我们对内存管理有了更深入的理解和认识。
内存是计算机用于存储正在运行的程序和数据的地方。
如果没有有效的内存管理机制,计算机系统将无法高效地运行多个程序,甚至可能会出现内存泄漏、内存不足等严重问题。
在实验中,我们首先接触到的是内存分配策略。
常见的内存分配策略包括连续分配和离散分配。
连续分配是将内存空间视为一个连续的地址空间,程序和数据被依次分配到连续的内存区域。
这种方式简单直观,但容易产生内存碎片,降低内存利用率。
离散分配则将内存分成大小相等或不等的块,根据需求进行分配。
其中分页存储管理和分段存储管理是两种常见的离散分配方式。
分页存储管理将内存空间划分为固定大小的页,程序也被分成相同大小的页,通过页表进行映射。
分段存储管理则根据程序的逻辑结构将其分成不同的段,如代码段、数据段等,每个段有不同的访问权限和长度。
接下来,我们研究了内存回收算法。
当程序不再使用分配的内存时,操作系统需要回收这些内存以便再次分配。
常见的内存回收算法有首次适应算法、最佳适应算法和最坏适应算法。
首次适应算法从内存的起始位置开始查找,找到第一个满足需求的空闲区域进行分配;最佳适应算法则选择大小最接近需求的空闲区域进行分配;最坏适应算法选择最大的空闲区域进行分配。
为了更直观地理解内存管理的过程,我们通过编程实现了一些简单的内存管理算法。
在编程过程中,我们深刻体会到了数据结构和算法的重要性。
例如,使用链表或二叉树等数据结构来表示空闲内存区域,可以提高内存分配和回收的效率。
在实验中,我们还遇到了一些实际的问题和挑战。
比如,如何处理内存碎片的问题。
内存碎片是指内存中存在一些无法被有效利用的小空闲区域。
为了解决这个问题,我们采用了内存紧缩技术,将分散的空闲区域合并成较大的连续区域。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验四内存管理模拟实验模拟实现一个简单的固定(可变)分区存储管理系统1.实验目的通过本次课程设计,掌握了如何进行内存的分区管理,强化了对首次适应分配算法和分区回收算法的理解。
2.实验内容(1)建立相关的数据结构,作业控制块、已分配分区及未分配分区(2)实现一个分区分配算法,如最先适应算法、最优或最坏适应分配算法(3)实现一个分区回收算法(4)给定一个作业/进程,选择一个分配或回收算法,实现分区存储的模拟管理图1.流程图3.实验步骤首先,初始化函数initial()将分区表初始化并创建空闲分区列表,空闲区第一块的长度是30,以后的每个块长度比前一个的长度长20。
frees[0].length=30第二块的长度比第一块长20,第三块比第二块长20,以此类推。
frees[i].length=frees[i-1].length+20;下一块空闲区的首地址是上一块空闲区的首地址与上一块空闲区长度的和。
frees[i].front=frees[i-1].front+frees[i-1].length;分配区的首地址和长度都初始化为零occupys[i].front=0;occupys[i].length=0;显示函数show()是显示当前的空闲分区表和当前的已分配表的具体类容,分区的有起始地址、长度以及状态,利用for语句循环输出。
有一定的格式,使得输出比较美观好看。
assign()函数是运用首次适应分配算法进行分区,从链首开始顺序查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲链中。
若从链首直至链尾都不能找到一个能满足要求的分区,则此次内存分配失败,返回。
这个算法倾向于优先利用内存中低址部分被的空闲分区,从而保留了高址部分的的大空闲区。
着给为以后到达的大作业分配大的内存空间创造了条件。
它的缺点是低地址部分不断被划分,会留下很多难以利用的、很小的空闲分区,而每次查找又都是从低址部分开始,这样无疑会增加查找可用空闲分区的开销。
分配内存,从空闲的分区表中找到所需大小的分区。
设请求的分区的大小为job_length,表中每个空闲分区的大小可表示为free[i].length。
如果frees[i].length>=job_length,即空闲空间I的长度大于等于作业的长度将空闲标志位设置为1,如果不满足这个条件则输出:“对不起,当前没有满足你申请长度的空闲内存,请稍后再试!”。
如果frees[i].length>=job_length空闲区空间I的长度不大于作业长度,I的值加1判断下一个空闲区空间是否大于作业的长度。
把未用的空闲空间的首地址付给已用空间的首地址,已用空间的长度为作业的长度,已用空间数量加1。
如果(frees[i].length>job_length),空间的长度大于作业的长度,frees[i].front+=job_length; 空闲空间的起始首地址=原空闲区间的起始长度加作业长度frees[i].length-=job_length;空闲区间的长度=原空闲区间的长度-作业的长度。
如果空间的长度与作业的长度相等,空闲区向前移一位,空闲区的数量也减一。
这样判断所有情况并相应分配之后,内存空间分配成功。
第二个操作为:撤消相应作业。
在这个操作中,进行了以下步骤:(1)按照系统提示输入将要撤消的作业名;(2)判断该作业是否存在若不存在:输出“没有这个作业名,请重新输入作业名”;若存在:则先分别用flag,start,len保存该作业在分配区表的位置i,内存空间的首地址以及长度。
接着根据回收区的首地址,即该作业的首地址,从空闲区表中找到相应的插入点,将其加入空闲表,此时可能出现以下三种情况之一:1 .回收区只与插入点前一个空闲分区F1相邻接即(frees[i].front+frees[i].length)==start),此时判断其是否与后一个空闲分区F2相邻接,又分两种情况:若相邻接,则将三个分区合并,修改新的空闲分区的首地址和长度。
新的首地址为F1的首地址,长度为三个分区长度之和,相应的代码为:frees[i].length=frees[i].length+frees[i+1].length+len;,并相应的空闲区表。
若不相邻接,即合并后的首应将回收区与插入点的前一分区合并,则不须为回收分区分配新的表项,只须修改其前一分区的大小。
该大小为F1与当前作业大小之和。
frees[i].length+=len;2 .回收分区与插入点前一个空闲分区不邻接但与后一空闲分区F2邻接。
此时应合并当前作业分区与F2分区,合并后的分区首地址为当前作业首地址start,长度为两个分区长度之和。
代码为:frees[i].front=start; frees[i].length+=len;3.回收分区既不与插入点前一空闲分区相邻接,也不与后一空闲分区相邻接。
此时只须将该回收分区插入空闲区表即可。
此时空闲区的数量加1。
将回收区加入空闲区表后还须修改分配区表内容。
具体为:修改分配区表中回收区(第一区)之后的各区指针,使其依次前移一位,即occupys[i]=occupys[i+1];同时已分配分区数量减1,即occupy_quantity--;最后输出内存空间回收完毕!即完成了撤消作业并回收相应空间的操作。
图2.初始化空闲分区列表图3.内存空间分配1图4.内存空间分配2图5.内存回收4.实验总结动态分区分配是根据进程的实际需要,动态地为之分配内存空间。
程序中采用空闲分区表,用于纪录每个空闲分区的情况。
每个空闲分区占一个表目,表目中包括起始地址、长度和状态。
采用已分配表,用于存放请求的作业,每个作业占一个表目,包括起始地址、长度和作业名。
程序调用initial()函数实现对空闲分区的初始化。
将作业装入内存时,运用首次适应分配算法。
程序中调用assign()实现,分配内存时,从表首开始查找,直至找到一个大小能满足要求的空闲分区为止;然后再按照作业的大小,从该分区中划出一块内存空间分配给请求者,余下的空闲分区仍留在空闲表中。
若不能找到满足要求的空闲区,则此次内存分配失败,返回。
回收内存,即撤销某些作业,调用撤销函数cancel(),根据所撤销作业的首址,从空闲区表中找到相应的插入点,回收内存包括四种情况:(1)回收区与前一空闲分区相邻接,此时将回收区与前一分区合并,并修改前一分区的大小;(2)回收区与后一空闲分区相邻接,此时将回收区与后一分区合并,并修改后一分区的首址和大小;(3)回收区同时与前、后分区相邻接,则将三个分区合并,使用前一分区的首址,大小为三分区大小之和;(4)回收区不与空闲分区相邻,则重新建立一新表项,填写首址和大小,插入表中相应位置。
函数show()用于显示空闲区表和已分配表时,运用for循环,依次显示每个空闲区表和已分配表的信息。
#include<stdlib.h>#include<stdio.h>#include<iostream.h>#include<string.h>#include<iomanip.h>const int MAXJOB=5;//定义表最大记录数typedef struct node{int front;int length;char data[20];}job;//定义job类型的数据类型job frees[MAXJOB];//定义空闲区表int free_quantity;job occupys[MAXJOB];//定义已分配区表int occupy_quantity;//初始化并创建空闲分区表函数int initial(){int i;frees[0].front=0;frees[0].length=30;occupys[0].front=0;occupys[0].length=0;strcpy(frees[0].data,"free");for(i=1;i<MAXJOB;i++){frees[i].front=frees[i-1].front+frees[i-1].length;frees[i].length=frees[i-1].length+20;strcpy(frees[i].data,"free");occupys[i].front=0;occupys[i].length=0;strcpy(occupys[i].data," ");}free_quantity=MAXJOB;occupy_quantity=0;return 1;}//显示函数void show(){int i;printf("----------------------------------------------------------\n");printf("当前空闲分区表如下:\n");printf("起始地址长度状态\n");for(i=0;i<free_quantity;i++){printf("%5d %8d %s\n",frees[i].fro nt,frees[i].length,frees[i].data);}printf("----------------------------------------------------------\n");printf("当前已分配表如下:\n");printf("起始地址长度占用作业名\n");for(i=0;i<occupy_quantity;i++){printf("%5d %6d %s\n",occupys[ i].front,occupys[i].length,occupys[i].data);}printf("----------------------------------------------------------\n");}//首次适应分配算法void assign(){char job_name[20];int job_length;int i,j,flag,t;printf("请输入新申请内存空间的作业名和空间大小:");scanf("%s",job_name);scanf("%d",&job_length);flag=0;for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length) //如果空闲空间I的长度>=作业长度{flag=1; //空闲标志位就置}}if(flag==0){printf("对不起,当前没有能满足你申请长度的空闲内存,请稍候再试!\n");}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,job_nam e);//已用空间的内容为作业名occupys[occupy_quantity].length=job_length;//已用空间的长度为作业的长度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--;//空闲区间的数量减一}printf("内存空间分配成功!\n");}}//撤消作业void cancel(){char job_name[20];int i,j,flag,p=0;int start;int len;printf("请输入要撤消的作业名:");scanf("%s",job_name);flag=0;for(i=0;i<occupy_quantity;i++){if(!strcmp(occupys[i].data,job_name))//当输入作业名匹配时{flag=i;//把i的值赋给flag;start=occupys[i].front;//把已用空间的首地址赋给startlen=occupys[i].length;//把已用空间的长度赋给len}}if(flag==0){printf("没有这个作业名,请重新输入作业名!\n");}else{ //加入空闲表for(i=0;i<free_quantity;i++){if((frees[i].front+frees[i].length)==start)//上空{if(((i+1)<free_quantity)&&(frees[i+1].front==start+l en))//下空{//第i个空闲区间的长度=第i个空闲区间的长度+第i+1个空闲区间的长度(下空闲区)+lengthfrees[i].length=frees[i].length+frees[i+1].length+len;for(j=i+1;j<free_quantity;j++){frees[j]=frees[j+1];//空闲区间前移一位}free_quantity--;//空闲区的数量渐少了一个p=1;}else{frees[i].length+=len;//(上空下不空)第i个空闲区间的长度=第i个空闲区间的长度+length,空闲区个数不变p=1;}}if(frees[i].front==(start+len))//下空上不空{frees[i].front=start;//起始地址等于待回收地址frees[i].length+=len;//第i个空闲区间的长度=第i个空闲区间的长度+lengthp=1;}}if(p==0) //上下空闲区都不空(直接在空闲区表中找一个空表目,将其内容插入){frees[free_quantity].front=start;frees[free_quantity].length=len;free_quantity++; //空闲区的数量加}//删除分配表中的该作业for(i=flag;i<occupy_quantity;i++){occupys[i]=occupys[i+1];}occupy_quantity--;//已用的区的数量printf("内存空间回收完毕!\n");}}//主函数void main(){int flag=0;int t=1;int chioce=0;printf("|--------------------------------------------------|\n");printf(" |可变分区存储管理模拟系统|\n");printf("|--------------------------------------------------|\n");printf(" |菜单:(0)退出|\n");printf(" | |\n");printf(" |(1)申请空间(2)撤消作业|\n");printf(" | |\n");printf(" |(3)显示空闲表和分配表|\n");printf("|--------------------------------------------------|\n");initial();flag=initial();while(flag==1){printf("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^\n");printf("请选择:");scanf("%d",&chioce);switch(chioce){case 1:assign(); break;case 2:cancel(); break;case 3:show(); break;case 0:flag=0; break;default:printf("选择错误!");}}// return 0;}。