操作系统-请求页式存储管理实验报告分析解析

合集下载

操作系统实验报告存储管理

操作系统实验报告存储管理

操作系统上机实验报告实验名称:存储管理实验目的:通过请求页式存储管理页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理页面置换算法。

实验内容:1.设计一个虚拟存储区和内存工作区;例如内存工作区大小为9个内存块,假设系统中最多可运行3个进程,每个进程分配3个内存块;2.模拟实现FIFO、LRU、OPT算法,给出页面走向,可计算缺页率;3.根据实验结果比较几种算法的差别。

实验步骤及分析:(一)FIFO算法实现提示定义一个常量total_instruction来记录页面总共使用的次数;定义一个变量diseffect记录总共换入页面的次数。

利用公式diseffect/total_instruction*100%可以得到缺页率。

(1)初始化。

设置两个数组page[ap]和pagecontrol[pp]分别表示进程页面数和内存分配的页面数,并产生一个随机数序列pageorder[total_instruction ](这个序列由page[]的下标随机构成)表示待处理的进程页面顺序,diseffect置0。

(2)看pageorder[]中是否有下一个元素,若有,就由pageorder[]中获取该页面的下标,并转到(3);如果没有就转到(7)。

(3)如果该page已在内存中,就转到(2);否则就到(4),同时未命中的diseffect加1。

(4)观察pagecontrol是否占满,如果占满须将使用队列中最先进入的pagecontrol单元“清干净”,同时将对应的page[]单元置为“不在内存中”。

(5)将该page[]与pagecontrol[]建立关系。

可以改变pagecontrol[]的标志位,也可以采用指针链接,总之至少要使对应的pagecontrol单元包含两个信息:一是它被使用了,二是哪个page[]单元使用的。

Page[]单元也包含两个信息:对应的pagecontrol 单元号和本 page[]单元已在内存中。

操作系统存储管理实验报告

操作系统存储管理实验报告
4 / 37
操作系统实验·报告
typedef struct pfc_struct pfc_type; (2)模块结构 (伙伴系统) # define Inital 1024 //初始时的总内存
NODE root=(memory_node *)malloc(1*sizeof(memory_node));//根节点 int chip=0; // 记录总的碎片大小
total = 256 use =127 remain_max = 0 flag = 0 pid =0
total = 256 use = 0 remain_max = 256 flag = 0 pid =-1
total = 1024 use = 0 remain_max = 512 flag = 1 pid =-1
total = 512 use = 0 remain_max = 512 flag = 0 pid =-1
total = 512 use = 267 remain_max = 0 flag = 0 pid = -1
6 / 37
操作系统实验·报告
三、实验理论分析
7 / 37
操作系统实验·报告
(伙伴算法) Buddy System 是一种经典的内存管理算法。在 Unix 和 Linux 操作系统中都有用到。其 作用是减少存储空间中的空洞、减少碎片、增加利用率。避免外碎片的方法有两种: a.利用分页单元把一组非连续的空闲页框映射到非连续的线性地址区间。 b.开发适当的技术来记录现存的空闲连续页框块的情况,以尽量避免为满足对小块的 请 求而把大块的空闲块进行分割。 基于下面三种原因,内核选择第二种避免方法: a.在某些情况下,连续的页框确实必要。 b.即使连续页框的分配不是很必要,它在保持内核页表不变方面所起的作用也是不容 忽视的。假如修改页表,则导致平均访存次数增加,从而频繁刷新 TLB。 c.通过 4M 的页可以访问大块连续的物理内存,相对于 4K 页的使用,TLB 未命中率降 低,加快平均访存速度。 Buddy 算法将所有空闲页框分组为 10 个块链表,每个块链表分别包含 1,2,4,8,16,32,64,128,256,512 个连续的页框,每个块的第一个页框的物理地址是该块 大小的整数倍。如,大小为 16 个页框的块,其起始地址是 16*2^12 的倍数。 例,假设要请求一个 128 个页框的块,算法先检查 128 个页框的链表是否有空闲块, 如果没有则查 256 个页框的链表,有则将 256 个页框的块分裂两份,一 份使用,一份 插入 128 个页框的链表。如果还没有,就查 512 个页框的链表,有的话就分裂为 128, 128,256,一个 128 使用,剩余两个插入对应链 表。如果在 512 还没查到,则返回 出错信号。 回收过程相反,内核试图把大小为 b 的空闲伙伴合并为一个大小为 2b 的单独块,满足 以下条件的两个块称为伙伴: a.两个块具有相同的大小,记做 b。 b.它们的物理地址是连续的。 c.第一个块的第一个页框的物理地址是 2*b*2^12 的倍数。 该算法迭代,如果成功合并所释放的块,会试图合并 2b 的块来形成更大的块。 为了模拟 Buddy System 算法,我采用了数的数据结构,并使用了结构体,来记录各项 数据与标记,虽然不是真正的操作系统使用的方法,但成功模拟了插入和回收的过程。 在回收时我采用物理上的合并——即删除实际的物理节点,释放空间。然而实际中可 能根据需要仅仅是删除了标记项,使之标记成没用过的,从而避免了合并,会提高下 一次的插入操作。 碎片百分比 = 碎片总大小/总内存大小 (置换算法)

存储管理实验报告_6

存储管理实验报告_6

昆明理工大学信息工程与自动化学院学生实验报告(2012 —2013 学年第二学期)一、实验目的存储管理的主要功能之一是合理地分配空间。

请求页式管理是一种常用的虚拟存储管理技术。

通过本次实验, 要求学生通过编写和调试地址转换过程的模拟程序以加强对地址转换过程的了解, 通过请求页式存储管理中页面置换算法模拟设计, 了解虚拟存储技术的特点, 掌握请求页式存储管理的页面置换算法。

二、实验原理及基本技术路线图(方框原理图)用C或C++语言模拟实现请求式分页管理。

要求实现: 页表的数据结构、分页式内存空间的分配及回收(建议采用位图法)、地址重定位、页面置换算法(从FIFO,LRU,NRU中任选一种)。

int subareaSize[num]={8,12,16,32,24,16,64,128,40,64};//分区大小Process *pro=NULL;//保持进程信息int ProcessNum=0;//进程数目int applyProcessNum=0;//每次申请进程数目int maxApplyNum=0;//最大可申请数目int *applyIndex=NULL;//申请进程队列int totalApplyNum=0;//申请总数int *assignPointer=NULL;//已分配内存的进程队列int assignFlag=0;//分配索引, 表示已申请队列已分配的进程数int exeIndex;//执行的进程号Node *subareaNode=new Node[3];//分区回收时, 进程所在分区及其前, 后分区信息LinkList createLinkList(int n );//建立空闲分区链Node firstFit(LinkList &head,Process pro);//首次适应算法Node nestFit(LinkList &head,Process pro,Node flag);//循环适应算法Node bestFit(LinkList &head,Process pro);//最佳适应算法Node worstFit(LinkList &head,Process pro);//最坏适应算法Node assign(LinkList &head,int orderIndex,int index,Node flagNode);//一次分区分配int assignMemory(LinkList &head);//内存分配void insertNode(LinkList &head,Node q,int index);//插入节点Node deleteNode(LinkList &head,int index);//删除节点int display(LinkList &head);//打印分区分配情况int lowAttemper(int *excursionPointer);//低级调度int findSubarea(LinkList &head,int index);//回收内存int creatProcess();//创建进程Process* randomCreatPro(int n);//随机产生进程下面是各种方法简述:(1) 最优替换算法, 即OPT算法。

实验四操作系统存储管理实验报告

实验四操作系统存储管理实验报告

实验四操作系统存储管理实验报告一、实验目的本次实验的主要目的是深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握内存分配与回收、页面置换算法等关键概念,并能够分析和解决存储管理中可能出现的问题。

二、实验环境本次实验在装有 Windows 操作系统的计算机上进行,使用了 Visual Studio 等编程工具和相关的调试环境。

三、实验内容(一)内存分配与回收算法实现1、首次适应算法首次适应算法从内存的起始位置开始查找,找到第一个能够满足需求的空闲分区进行分配。

在实现过程中,我们通过建立一个空闲分区链表来管理内存空间,每次分配时从表头开始查找。

2、最佳适应算法最佳适应算法会选择能够满足需求且大小最小的空闲分区进行分配。

为了实现该算法,在空闲分区链表中,分区按照大小从小到大的顺序排列,这样在查找时能够快速找到最合适的分区。

3、最坏适应算法最坏适应算法则选择最大的空闲分区进行分配。

同样通过对空闲分区链表的排序和查找来实现。

(二)页面置换算法模拟1、先进先出(FIFO)页面置换算法FIFO 算法按照页面进入内存的先后顺序进行置换,即先进入内存的页面先被置换出去。

在模拟过程中,使用一个队列来记录页面的进入顺序。

2、最近最久未使用(LRU)页面置换算法LRU 算法根据页面最近被使用的时间来决定置换顺序,最近最久未使用的页面将被置换。

通过为每个页面设置一个时间戳来记录其最近使用的时间,从而实现置换策略。

3、时钟(Clock)页面置换算法Clock 算法使用一个环形链表来模拟内存中的页面,通过指针的移动和页面的访问标志来决定置换页面。

四、实验步骤(一)内存分配与回收算法的实现步骤1、初始化内存空间,创建空闲分区链表,并为每个分区设置起始地址、大小和状态等信息。

2、对于首次适应算法,从链表表头开始遍历,找到第一个大小满足需求的空闲分区,进行分配,并修改分区的状态和大小。

3、对于最佳适应算法,在遍历链表时,选择大小最接近需求的空闲分区进行分配,并对链表进行相应的调整。

操作系统-请求页式存储管理实验报告分析解析

操作系统-请求页式存储管理实验报告分析解析

操作系统-请求页式存储管理实验报告分析解析实验背景在计算机系统中,内存是一项很重要的资源。

其中,操作系统需要管理内存,以便为用户进程和内核提供适当的内存空间。

页式内存管理是操作系统能够管理和维护内存的一种方式。

在页式内存管理中,主存分为固定大小的框架,称为页框,而进程的地址空间被分割为固定大小的页。

页式内存管理系统采用了一种称为“请求页式存储”的技术,允许进程只存取正在使用的那些页面。

这样可以节省空间,并且提高了处理器访问内存的速度。

实验环境本次实验使用的操作系统是 Ubuntu 20.04 LTS 操作系统。

实验目标本次实验的主要目标是通过模拟请求页式内存管理系统,来了解和深入理解页式内存管理技术。

本次实验需要完成以下任务:1.编写一个简单的请求页式存储模拟器;2.使用该模拟器对作业和内存进行模拟;3.分析模拟结果并撰写实验报告。

实验过程阅读并理解作业说明在开始实验之前,我们首先需要阅读和了解具体的作业说明。

在本次实验中,我们需要完成一个请求页式存储模拟器,以及使用该模拟器对作业与内存进行模拟。

编写模拟器在了解了作业说明后,我们开始按照作业的要求,编写请求页式内存管理模拟器。

在这里,我们需要使用到Python 编程语言。

实际上,我们在编写该模拟器时,主要分为以下几步:1.文件操作:首先,我们需要通过读取文件中的数据来模拟进程对内存的请求。

在输入文件中,每一行表示一个请求,包含了进程 ID、请求的地址和访问类型。

2.内存分配:接着,我们需要模拟请求页式内存管理系统中对于内存分配的操作,即在访问时,将需要的页加载到内存中,如果内存已满,则需要选择一个页面将其从内存中移除,为新的页面腾出空间。

3.页面置换:如果进行页面置换,则需要选出最久未访问的页面并移出内存,空出空间用于新的页面,这就是所谓的“最久未使用”(LRU)策略。

进行模拟有了模拟器之后,我们就可以针对不同的作业和内存大小进行实验。

在实验的过程中,我们可以观察不同大小的内存和不同的作业怎样影响模拟的结果。

实验六请求分页存储管理

实验六请求分页存储管理

实验六:请求分页存储管理一.实验目的深入理解请求页式存储管理的基本概念和实现方法,重点认识其中的地址变换、缺页中断、置换算法等实现思想。

二.实验属性该实验为综合性、设计性实验。

三.实验仪器设备及器材普通PC386以上微机四.实验要求本实验要求2学时完成。

本实验要求完成如下任务:(1)建立相关的数据结构:页表、页表寄存器、存储块表等;(2)指定分配给进程的内存物理块数,设定进程的页面访问顺序;(3)设计页面置换算法,可以选择OPT、FIFO、LRU等,并计算相应的缺页率,以比较它们的优劣;(4)编写地址转换函数,实现通过查找页表完成逻辑地址到物理地址的转换;若发生缺页则选择某种置换算法(OPT、FIFO、LRU等)完成页面的交换;(5)将整个过程可视化显示出来。

实验前应复习实验中所涉及的理论知识和算法,针对实验要求完成基本代码编写并完成预习报告、实验中认真调试所编代码并进行必要的测试、记录并分析实验结果。

实验后认真书写符合规范格式的实验报告(参见附录A),并要求用正规的实验报告纸和封面装订整齐,按时上交。

三、设计过程3.1算法原理分析OPT算法是未来最远出现,当当前内存中没有正要访问的页面时,置换出当前页面中在未来的访问页中最远出现的页面或再也不出现的页面。

FIFO算法是先进先出,当当前内存中没有正要访问的页面时,置换出最先进来的页面。

LRU算法是最近最久未使用,当当前内存中没有正要访问的页面时,置换出在当前页面中最近最久没有使用的页面。

3.2数据定义int length,num_page,count,seed; //length记录访问串的长度,num_page页面数,count记录缺页次数int result[20][30],order[30],a[10]; //result记录结果,order存储访问串,a存储当前页面中的值int pos1,flag1,flag2,flag3; //pos1位置变量,flag1等为标志变量 char result1[30]; //记录缺页数组 void opt() //最佳void fifo() //先进先出bool search(int n) //查找当前内存中是否已存在该页3.3流程图与运行截图图6.1 FIFO ()函数流程图;否是 是否 开始得到执行的指令指令是否在内存中最先存入指令被淘汰下面是否还有指令 结束得出命中率图2.2 OPT算法流程图四、小结本次课程设计目的是通过请求页式管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。

《操作系统》存储管理实验报告

《操作系统》存储管理实验报告

《操作系统》存储管理实验报告操作系统是计算机系统中最基础、最核心的软件之一,负责管理计算机硬件资源和提供资源的分配与调度。

而存储管理是操作系统中的重要组成部分,它负责管理计算机的内存,包括内存的分配、回收、保护等操作。

本文将针对存储管理进行实验,并撰写实验报告。

本次实验主要涉及以下内容:内存的分配与回收、内存的保护。

实验过程中,我首先根据操作系统的要求,设计了相应的算法用于内存的分配与回收。

并通过编写程序,验证了算法的正确性。

随后,我进一步研究了内存的保护机制,通过设置访问权限位和访问控制表,实现了对内存的合理保护。

在内存的分配与回收方面,我设计了一种简单的算法,首次适应算法。

具体实现如下:首先,将内存分为若干个块,每个块的大小为固定值。

当需要分配内存时,首先遍历内存块列表,找到第一个大小合适的块,将其分配给进程。

当进程终止时,将其占用的内存块回收,以便后续进程使用。

通过编写程序进行测试,结果表明该算法能够正确地进行内存的分配与回收。

在内存的保护方面,我采用了访问权限位和访问控制表的方式进行。

具体实现如下:首先,为每个进程分配一组访问权限位,记录了该进程能够访问的内存区域。

同时,设置一个访问控制表,记录了每个内存块的权限。

当进程访问一些内存块时,首先检查该进程的访问权限位,再与访问控制表中的权限进行比较,以确定该进程是否有权限访问该内存块。

通过编写程序进行测试,证明了该机制能够有效地保护内存。

总结来说,本次实验主要涉及了操作系统中的存储管理部分,包括内存的分配与回收、内存的保护。

通过设计算法和编写程序,我成功地实现了这些功能,并验证了其正确性。

通过本次实验,我进一步加深了对操作系统存储管理的理解,提高了编程和设计的能力。

存储管理实验报告

存储管理实验报告

存储管理实验报告题目:1。

存储管理描述请求分页存储管理。

一.产生一个作业及作业页面序列P(pi),例如:P(0,2,3,4,1,5,2,3,0,4,1,5)。

二.分配物理内存块数M。

三.采用FIFO,LRU置换算法。

四.设计原理:本程序提供两种分区管理法供用户使用,这两种算法是最佳适应算法和首次适应算法。

最佳适应算法要求将所有的空闲区,按其大小以递增的顺序形成一空闲区链。

这样,第一次找到的满足要求的空闲区,必然是最优的。

但该算法会留下许多这样难以利用的小空闲区。

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

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

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

三.不足之处:该程序可以用文件形式输入作业的信息,但是该文件没有绑定在程序中。

不过,用户用键盘输入的作业的信息会自动保存到该文件中,下次当以文件形式输入作业信息时,文件中的内容是上一次用户用键盘输入的内容。

四.源程序以及解释:#include<stdio.h>#include<time.h>#include<stdlib.h>int memoryStartAddress = -1;int memorySize = -1;struct jobList//作业后备队列的链结点{int id; //作业的ID号int size; //作业的大小int status; //作业状态struct jobList *next;};struct freeList //空闲链的链结点{int startAddress; //空闲分区的首地址int size; //空闲分区的大小struct freeList *next;};struct usedList //已分配内存的作业链{int startAddress; //以分配内存的首地址int jobID;struct usedList *next;};void errorMessage(void) //出错信息{printf("\n\t错误!\a");printf("\n按任意键继续!");getch();exit(1);}void openFile(FILE **fp,char *filename,char *mode) //打开文件函数{if((*fp = fopen(filename,mode)) == NULL){printf("\n不能打开%s.",filename);errorMessage();}}void makeFreeNode(struct freeList **empty,int startAddress,int size)//申请内存空间{if((*empty = malloc(sizeof(struct freeList))) == NULL){printf("\n没有足够空间.");errorMessage();}(*empty)->startAddress = startAddress; //当有足够空间时,则分配(*empty)->size = size;(*empty)->next = NULL;}void iniMemory(void) //输入要求分配内存的首地址,大小{char MSA[10],MS[10];printf("\n请输入要分配内存的首地址!");scanf("%s",MSA);memoryStartAddress = atoi(MSA);printf("\n请输入要分配内存的大小!");scanf("%s",MS);memorySize = atoi(MS);}char selectFitMethod(void) //选择分区管理算法{FILE *fp;char fitMethod;do{printf("\n\n请选择分区管理的算法!\\n 1 最佳适应算法\\n 2 首次适应算法\n");fitMethod = getche();}while(fitMethod < '1' || fitMethod > '3'); //选择出错时openFile(&fp,"d:\\result.cl","a");switch(fitMethod){case '1':fprintf(fp,"\n\n\n\n\t 最佳适应算法");fprintf(fp,"\n**********************************************");break;case '2':fprintf(fp,"\n\n\n\n\t首次适应算法");fprintf(fp,"\n**********************************************");break;}fclose(fp);return fitMethod;}void inputJob(void) //输入作业的信息{int /*id,size, */status = 0,jobnum = 0;FILE *fp;char id[10],size[10];openFile(&fp,"d:\\job.cl","w");fprintf(fp,"作业名\t大小\t状态");printf("\n\n\n\n请输入作业名和大小!\n输入0 0退出,job_ID由数字组成\n\n\njob_ID\tsize\n");do{/* scanf("%d%d",&id,&size); */scanf("%s\t%s",id,size); //保存作业ID,大小if(atoi(id) > 0 && atoi(size) > 0){fprintf(fp,"\n%s\t%s\t%d",id,size,status);/* fprintf(fp,"\n%d\t%d\t%d",id,size,status); */jobnum++;}else break;}while(1);if(jobnum)printf("\n完成输入!");else{printf("\n没有请求分配内存.");errorMessage();}fclose(fp);}int makeJobList(struct jobList **jobs) //把作业插入分区{char jobID[10],size[10],status[10];struct jobList *rear;FILE *fp;openFile(&fp,"d:\\job.cl","r");fscanf(fp,"%s%s%s",jobID,size,status);if((*jobs = malloc(sizeof(struct jobList))) == NULL) //当没有空闲分区时{printf("\n没有足够空间.");fclose(fp);errorMessage();}rear = *jobs;(*jobs) -> next = NULL;while(!feof(fp)){struct jobList *p;fscanf(fp,"%s%s%s",jobID,size,status);if((p = malloc(sizeof(struct jobList))) == NULL){printf("\n没有足够空间.");fclose(fp);errorMessage();}p -> next = rear -> next; //插入已在分区的作业队列中rear -> next = p;rear = rear -> next;rear -> id = atoi(jobID);rear -> size = atoi(size);rear -> status = atoi(status);}fclose(fp);return 0;}int updateJobFile(struct jobList *jobs){FILE *fp;struct jobList *p;openFile(&fp,"d:\\job.cl","w");fprintf(fp,"job_ID\tsize\tstatus");for(p = jobs -> next;p;p = p -> next)fprintf(fp,"\n%d\t%d\t%d",p -> id,p -> size,p -> status);fclose(fp);return 0;}int showFreeList(struct freeList *empty) //在屏幕上显示空闲分区{FILE *fp;struct freeList *p = empty -> next;int count = 0;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n显示空闲内存");printf("\n\n显示空闲内存");if(p){fprintf(fp,"\nnumber\tsize\tstartAddress");printf("\n序号\t大小\t开始地址"); //显示空闲分区的大小和首地址for(;p;p = p -> next){fprintf(fp,"\n%d\t%d\t%d",++count,p -> size,p -> startAddress);printf("\n%d\t%d\t%d",count,p -> size,p -> startAddress);}fclose(fp);return 1;}Else //没有空闲分区{fprintf(fp,"\n内存已分配完!");printf("\n内存已分配完!");fclose(fp);return 0;}}void getJobInfo(struct jobList *jobs,int id,int *size,int *status) //查找作业是否在分区中{struct jobList *p = jobs->next;while(p && p->id != id) //删除作业p = p->next;if(p == NULL){printf("\n不能找到作业: %d .",id);errorMessage();}else{*size = p -> size;*status = p -> status;}}void updateJobStatus(struct jobList **jobs,int id,int status) //改变作业的状态{struct jobList *p = (*jobs)->next;while(p && p->id != id)p = p->next;if(p == NULL){printf("\n不能找到作业: %d .",id);errorMessage();}p -> status = status; //作业状态}int showUsedList(struct jobList *jobs,struct usedList *used) //显示以分配的分区{FILE *fp;struct usedList *p = used -> next;int count = 0,size,status;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n显示已分配的内存");printf("\n\n显示已分配的内存");if(p){fprintf(fp,"\nnumber\t作业名\t大小\t开始地址");printf("\nnumber\t作业名\t大小\t开始地址"); //显示分区中的作业信息for(;p;p = p -> next){getJobInfo(jobs,p -> jobID,&size,&status);fprintf(fp,"\n%d\t%d\t%d\t%d",++count,p -> jobID,size,p -> startAddress);printf("\n%d\t%d\t%d\t%d",count,p -> jobID,size,p -> startAddress);}fclose(fp);return 1;}Else //分区中没有作业{fprintf(fp,"\n内存中没有作业.");printf("\n内存中没有作业.");fclose(fp);return 0;}}int showJobList(struct jobList *jobs) //分区上的作业{struct jobList *p;p = jobs->next;if(p == NULL){printf("\n列表上没有作业.");return 0;}printf("\n\nT列表上的作业如下:\n作业名\t大小\t状态"); //显示作业信息while(p)printf("\n%d\t%d\t%d",p->id,p->size,p->status);p = p->next;}return 1;}void moveFragment(struct jobList *jobs,struct freeList **empty,struct usedList **used) //当回收一部分分区后,进行碎片紧凑{int size,status;struct usedList *p;int address = memoryStartAddress;if((*empty)->next == NULL) //当没有空闲分区分配时,可以回收已分配内存{printf("\n内存已用完.\\n你可以先回收一些内存或者\\n按任意键再试一次!");getch();return;}for(p = (*used) -> next;p;p = p-> next) //插入作业{p -> startAddress = address;getJobInfo(jobs,p -> jobID,&size,&status);address += size;}(*empty) -> next -> startAddress = address; //删除作业,回收内存(*empty) -> next -> size = memorySize - (address - memoryStartAddress);(*empty) -> next -> next = NULL;}void order(struct freeList **empty,int bySize,int inc) //按顺序排列分区的作业{struct freeList *p,*q,*temp;int startAddress,size;for(p = (*empty) -> next;p;p = p -> next){for(temp = q = p;q;q = q -> next){switch(bySize){case 0 : switch(inc){case 0:if(q->size < temp->size) //交换作业位置temp = q;break;default:if(q->size > temp->size)//交换作业位置temp = q;break;} break;default: switch(inc){case 0:if(q->startAddress < temp->startAddress)temp = q;break; //交换作业位置default:if(q->startAddress > temp->startAddress)temp = q;break; //交换作业位置} break;}}if(temp != p){startAddress = p->startAddress;size = p->size;p->startAddress = temp->startAddress;p->size = temp->size;temp->startAddress = startAddress;temp->size = size;}}}int allocate(struct freeList **empty,int size) //按要求把分区分该作业{struct freeList *p,*prep;int startAddress = -1;p = (*empty) -> next;while(p && p->size < size)//没有足够分区,删除作业p = p -> next;if(p != NULL){if(p -> size > size) //当有足够分区,直接分配{startAddress = p -> startAddress;p -> startAddress += size;p -> size -= size;}else //将整个分区分给一个作业{startAddress = p -> startAddress;prep = *empty;while(prep -> next != p)prep = prep -> next;prep -> next = p -> next;free(p);}}else printf("\n你可以拼接碎片."); /* Unsuccessful ! */return startAddress;}void insertUsedNode(struct usedList **used,int id,int startAddress)//在分区中插入作业{struct usedList *q,*r,*prer;if((q = malloc(sizeof(struct usedList))) == NULL) //没有足够空间时{printf("\nNot enough to allocate for the used node .");errorMessage();}q -> startAddress = startAddress; //插入作业q -> jobID = id;prer = *used;r = (*used) -> next;while(r && r->startAddress < startAddress){prer = r;r = r -> next;}q -> next = prer -> next;prer -> next = q;}int finishJob(struct usedList **used,int id,int *startAddress) //删除作业,回收分区{struct usedList *p,*prep;prep = *used;p = prep -> next;while(p && p -> jobID != id) //删除作业{prep = p;p = p -> next;}if(p == NULL){printf("\n作业: %d 不在内存!",id); //找不到要删除的作业return 0;}else{*startAddress = p->startAddress;prep -> next = p -> next;free(p);return 1;}}void insertFreeNode(struct freeList **empty,int startAddress,int size)//插入空闲分区{struct freeList *p,*q,*r;for(p = *empty;p -> next;p = p -> next) ;if(p == *empty || p -> startAddress + p -> size < startAddress)//对空闲分区进行排列{makeFreeNode(&r,startAddress,size);r -> next = p -> next;p -> next = r;return ;}if(p -> startAddress + p -> size == startAddress) //插入空闲分区{p -> size += size;return ;}q = (*empty) -> next;if(startAddress + size == q -> startAddress) //插入空闲分区{q -> startAddress = startAddress;q -> size += size;}else if(startAddress + size < q -> startAddress) //插入空闲分区{makeFreeNode(&r,startAddress,size);r -> next = (*empty) -> next;(*empty) -> next = r;}else{while(q -> next && q -> startAddress < startAddress) //插入空闲分区{p = q;q = q -> next;}if(p -> startAddress + p -> size == startAddress &&\q -> startAddress == startAddress + size) //插入空闲分区{p -> size += size + q -> size;p -> next = q -> next;free(q);}else if(p -> startAddress + p -> size == startAddress &&\q -> startAddress != startAddress + size) //插入空闲分区{p -> size += size;}else if(p -> startAddress + p -> size != startAddress &&\q -> startAddress == startAddress + size) //插入空闲分区{q -> startAddress = startAddress;q -> size += size;}else{makeFreeNode(&r,startAddress,size); //申请作业空间r -> next = p -> next;p -> next = r;}}}void main(void){char fitMethod; //定义变量FILE *fp; //定义变量struct jobList *jobs; //定义一个队列struct freeList *empty;//定义一个队列struct usedList *used;//定义一个队列if((used = malloc(sizeof(struct usedList))) == NULL){printf("\n没有足够空间.");errorMessage();}used -> next = NULL;remove("d:\\result.cl");makeFreeNode(&empty,0,0);while(1) //界面设计{char ch,step; //定义变量int id,size,startAddress,status; //定义变量struct jobList *q;printf("\n 1 输入作业的信息.\\n 2 作业放到内存.\\n 3 完成作业,并回收内存.\\n 4 当前空闲的内存.\\n 5 当前已分配的内存.\\n 6 拼接碎片.\\n 7 退出.");printf("\n请选择.\n");step = getche();printf("\n");switch(step){case '1': //当选择1时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t输入作业的信息:)");used -> next = NULL; //初始化队列empty->next = NULL; //初始化队列iniMemory();makeFreeNode(&(empty->next),memoryStartAddress,memorySize);fprintf(fp,"\n\n\n你用文件形式输入吗?(Y/N) : ");//是否用文件形式输出printf("\n\n\n你用文件形式输入吗?(Y/N ): \n");ch = getche();fprintf(fp,"\n%c",ch);fclose(fp);if(ch != 'Y'&& ch != 'y') //当选择用文件形式输出时{inputJob();}makeJobList(&jobs);if(ch == 'Y'|| ch == 'y') //读入文件的作业信息{for(q = jobs->next;q;q = q->next){if(q->status == 1){startAddress = allocate(&empty,q->size);if(startAddress != -1){insertUsedNode(&used,q->id,startAddress);}}}}fitMethod = selectFitMethod();break;case '2': //当选择2时if(memoryStartAddress < 0 || memorySize < 1){printf("\n\nBad memory allocated !\a");break;}openFile(&fp,"d:\\result.cl","a"); //打开文件fprintf(fp,"\n\n\t把作业放到内存");fprintf(fp,"\n\n\n你用键盘输入作业信息吗?(Y/N): ");printf("\n\n\n你用键盘输入作业信息吗?(Y/N): \n");ch = getche();fprintf(fp,"\n%c",ch);fclose(fp);if(ch != 'Y' && ch != 'y') //把作业放到分区中{for(q = jobs->next;q;q = q->next){if(q->status == 0){switch(fitMethod) //用不同分区管理算法{case '1': order(&empty,0,0);break;case '2': order(&empty,0,1);break;case '3': order(&empty,1,0);break;case '4': order(&empty,1,1);break;}startAddress = allocate(&empty,q->size);if(startAddress != -1){insertUsedNode(&used,q->id,startAddress);//把作业插入到以分配内存中updateJobStatus(&jobs,q->id,1);}}}updateJobFile(jobs);}else{showJobList(jobs); //显示可操作的作业openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n请从上面的作业中选择一个作业,输入作业名.");printf("\n请从上面的作业中选择一个作业,输入作业名.");scanf("%d",&id);fprintf(fp,"%d\n",id);getJobInfo(jobs,id,&size,&status); //把作业放入内存switch(status) //作业的不同状态{case 0: printf("\nOk !作业的状态是运行状态!");fprintf(fp,"\nOk!作业的状态是运行状态!");fclose(fp);break;case 1: printf("\n作业在内存中!");fprintf(fp,"\n作业在内存中!");fclose(fp);goto label;case 2: printf("\n作业已完成!");fprintf(fp,"\n作业已完成!");fclose(fp);goto label;default:printf("\nUnexpected job status .Please check you job file.");fprintf(fp,"\nUnexpected job status .Please check you job file.");fclose(fp);errorMessage();}switch(fitMethod) //不同分区管理方法的实现{case '1': order(&empty,0,0);break;case '2': order(&empty,0,1);break;case '3': order(&empty,1,0);break;case '4': order(&empty,1,1);break;}startAddress = allocate(&empty,size);if(startAddress != -1){insertUsedNode(&used,id,startAddress); //插入作业updateJobStatus(&jobs,id,1); //改变作业状态updateJobFile(jobs);}}label : ;break;case '3': //当选择3时if(memoryStartAddress < 0 || memorySize < 1){printf("\n\nBad memory allocated !\a");break;}do{int i;openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t作业完成(回收内存)");fclose(fp);if(showUsedList(jobs,used) == 0)break;openFile(&fp,"d:\\result.cl","a"); //打开文件fprintf(fp,"\n请从上面的作业中选择一个作业,输入作业名.\n输入-1来结束测试.");printf("\n请从上面的作业中选择一个作业,输入作业名.\n 输入-1来结束测试.");scanf("%d",&id);fprintf(fp,"%d\n",id);fclose(fp);if(id == -1)break;getJobInfo(jobs,id,&size,&status); //把作业放入内存if(status == 1) //作业状态为运行时{i = finishJob(&used,id,&startAddress);if(i){insertFreeNode(&empty,startAddress,size); //插入空闲分区updateJobStatus(&jobs,id,2); //改变作业状态updateJobFile(jobs);}}else{if(status == 0 || status == 2){if(status == 0)printf("\n作业不在内存中!");else printf("\n作业已完成!");}else{printf("\nUnexpected job status .\Please check you job file.");errorMessage();}}}while(1);break;case '4': //当选择4时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t显示空闲内存");fclose(fp);showFreeList(empty);break;case '5': //当选择5时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t显示已分配内存");fclose(fp);showUsedList(jobs,used);break;case '6': //当选择6时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\t拼接碎片");fclose(fp);moveFragment(jobs,&empty,&used);break;case '7': //当选择7时openFile(&fp,"d:\\result.cl","a");fprintf(fp,"\n\n\tExit :(");fclose(fp);exit(0);default: printf("\n错误输入!");}}getch();}五.运行效果:1.运行EXE文件:2.首先要选择1,输入要分配内存的首地址,分区大小,输入作业的信息:3.按ENTER键后,选择分区管理算法:4.然后选择2,把作业放到内存:5.到此,用户就可以选择自己想要的操作功能,这里3为例:6.用户也可以选择其他功能,这里不作介绍。

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

操作系统实验三存储管理实验班级:学号:姓名:目录1. 实验目的 (2)2. 实验内容 (2)(1) 通过随机数产生一个指令序列,共320条指令 (2)(2) 将指令序列变换成为页地址流 (2)(3) 计算并输出下述各种算法在不同内存容量下的命中率 (2)3. 随机数产生办法 (3)环境说明 (3)4. 程序设计说明 (3)4.1.全局变量 (3)4.2.随机指令序列的产生 (4)4.3.FIFO算法 (4)4.4.LRU算法 (4)4.5.OPT算法 (5)5. 编程实现(源程序): (5)6. 运行结果及分析 (11)6.1.运行(以某两次运行结果为例,列表如下:) (11)6.2.Belady’s anomaly (11)1.实验目的存储管理的主要功能之一是合理地分配空间。

请求页式管理是一种常用的虚拟存储管理技术。

本实验的目的是通过请求页式存储管理中页面置换算法模拟设计,了解虚拟存储技术的特点,掌握请求页式存储管理的页面置换算法。

2.实验内容(1) 通过随机数产生一个指令序列,共320条指令指令的地址按下述原则生成:a) 50% 的指令是顺序执行的;b) 25% 的指令是均匀分布在前地址部分;c) 25% 的指令是均匀分布在后地址部分;具体的实施方法是:a) 在[0,319]的指令地址之间随机选取一起点m;b) 顺序执行一条指令,即执行地址为m+1的指令;c) 在前地址[0,m+1]中随机选取一条指令并执行,该指令的地址为m';d) 顺序执行一条指令,其地址为m'+1;e) 在后地址[m'+2,319]中随机选取一条指令并执行;f) 重复上述步骤a)~f),直到执行320次指令。

(2) 将指令序列变换成为页地址流设:a) 页面大小为1K;b) 用户内存容量为4页到32页;c) 用户虚存容量为32K。

在用户虚存中,按每K存放10条指令排列虚存地址,即320条指令在虚存中的存放方式为:第0条~第9条指令为第0页(对应虚存地址为[0,9]);第10条~第19条指令为第1页(对应虚存地址为[10,19]);……第310条~第319条指令为第31页(对应虚存地址为[310,319])。

按以上方式,用户指令可以组成32页。

(3) 计算并输出下述各种算法在不同内存容量下的命中率a) 先进先出的算法(FIFO);b) 最近最少使用算法(LRU);c) 最佳淘汰算法(OPT);命中率=1-页面失效次数/页地址流长度在本实验中,页地址流长度为320,页面失效次数为每次访问相应指令时,该指令所对应的页不在内存的次数。

3.随机数产生办法关于随机数产生办法,可以采用操作系统提供的函数,如Linux或UNIX系统提供函数srand()和rand(),分别进行初始化和产生随机数。

例如:srand();语句可以初始化一个随机数;a[0]=10*rand()/32767*319+1;a[1]=10*rand()/32767*a[0];…语句可以用来产生a[0]与a[1]中的随机数。

环境说明此实验采用的是Win7下Code::blocks 10.05编译器编程。

此word实验文档中采用notepad++的语法高亮。

4.程序设计说明4.1.全局变量const int maxn =320;//序列个数const int max = maxn +20;//数组大小const int maxp = max/10;//最大页数int inst[max];//指令序列int page[max];//页地址流int size;//内存能容纳的页数bool in[maxp];//该页是否在内存里,提高效率int pin[maxp];//现在在内存里的页其中in[]数组是为了方便直接判断该页是否在内存里,而不用遍历内存里所有页来判断。

fault_n用来记录缺页次数。

4.2.随机指令序列的产生按照实验要求的写了,但是由于没有考虑细节,开始时出了点问题。

(1)当m=319时,我们顺序执行m+1会产生第32页的页地址,从而使页地址没能按要求限制在[0, 31]之间。

解决方法:采用循环模加来避免超出范围。

(2)但是这样之后有可能出现模0的问题。

所以我索性将等于0的模数都赋值为160.最后的程序如下。

void produce_inst(){int m, n;int num =0;while(num < maxn){m = rand()% maxn;inst[num++]=(m+1)%maxn;if(num == maxn)break;m =(m+2)% maxn;if(m ==0) m =160;n = rand()% m;inst[num++]=(n+1)%maxn;if(num == maxn)break;n =(n+2)% maxn;m = maxn - n;if(m ==0) m =160;m = rand()% m + n;inst[num++]= m;}}4.3.FIFO算法定义变量ptr。

一开始先预调页填满内存。

在这一部分,ptr指向下一个要存放的位置。

之后继续执行剩下的指令。

此时,ptr表示队列最前面的位置,即最先进来的位置,也就是下一个要被替换的位置。

ptr用循环加,即模拟循环队列。

4.4.LRU算法定义数组ltu[],即last_time_use来记录该页最近被使用的时间。

定义变量ti模拟时间的变化,每执行一次加一。

这个算法,我没有预调页,而是直接执行所有指令。

若当前需要的页没在内存里,就寻找最近最少使用的页,也就是ltu[]最小的页,即最近一次使用时间离现在最久的页,然后替换掉它。

或者在内存还未满时,直接写入,这个我以初始化内存里所有页为-1来实现。

若已经在内存里了,则只遍历内存内的页,把当前页的最近使用时间改一下即可。

4.5.OPT算法定义数组ntu[], 即next_time_use来记录下一次被使用的时间,即将来最快使用时间。

初始化为-1.开始时预调页填满内存里的页。

同样利用变量ptr来表示下一个要存放的位置从而控制预调页的过程。

接着初始化ntu数组为-1。

然后求出每一页下一次被使用的指令号,以此代替使用时间。

如果所有剩下的序列都没有用该页时,则还是-1.这种值为-1的页显然是最佳替换对象。

然后执行所有剩下的指令。

当该页不在内存里时,遍历ntu数组,遇到-1的直接使用该页,没有则用ntu[]值最大的,也就是最晚使用的。

无论该页在不在内存里,因为这一次已经被使用了,所以都应该更新这个页的ntu[],只需往前看要执行的页流,记录下第一个遇到的该页即可。

如果没有找到同样添-1即可。

5.编程实现(源程序):#include <stdio.h>#include <stdlib.h>#include <time.h>#include <string.h>using namespace std;const int maxn =320;//序列个数const int max = maxn +20;//数组大小const int maxp = max/10;//最大页数int inst[max];//指令序列int page[max];//页地址流int size;//内存能容纳的页数bool in[maxp];//该页是否在内存里,提高效率int pin[maxp];//现在在内存里的页void welcome(){printf("******************************************\n");printf("** By schnee On2011-12-06 **\n");printf("** 班级:09211311 班内序号:30 **\n");printf("******************************************\n\n");}void input_hint(){printf("\n1--create new instruction sequence 2--set memory page number(4 to 32)\n");printf("3--solve by FIFO algorithm 4--solve by LRU algorithm\n");printf("5--solve by OPT algorithm 0--exit\n");printf("*********Please input Your choice: ");}/*通过随机数产生一个指令序列,共320条指令*/void produce_inst(){int m, n;int num =0;while(num < maxn){m = rand()% maxn;inst[num++]=(m+1)%maxn;if(num == maxn)break;m =(m+2)% maxn;if(m ==0) m =160;n = rand()% m;inst[num++]=(n+1)%maxn;if(num == maxn)break;n =(n+2)% maxn;m = maxn - n;if(m ==0) m =160;m = rand()% m + n;inst[num++]= m;}}/*将指令序列变换成为页地址流*/void turn_page_address(){for(int i=0; i<maxn; i++)page[i]= inst[i]/10;}void FIFO_solve(){memset(in,false,sizeof(in));int fault_n =0;//缺页率int ptr, i;//预调页填满空间ptr =0;//下一个要放的位置for(i=0; i<maxn && ptr<size; i++)if(!in[page[i]]){pin[ptr++]= page[i];in[page[i]]=true;fault_n++;}//继续执行剩下的指令ptr =0;//队列里最先进来的位置,即下一个要被替换的位置for(; i<maxn; i++)if(!in[page[i]]){in[pin[ptr]]=false;in[page[i]]=true;pin[ptr]= page[i];fault_n++;ptr =(ptr+1)% size;}printf("\nBy FIFO algorithm, the fault-page number is: %d\n", fault_n);printf(" the hit ratio is : %.2lf\n",(1-(fault_n+0.0)/320.0)); }void LRU_solve(){int ltu[maxp];//last_time_useint ti =1;//模拟时间int fault_n =0;memset(ltu,0,sizeof(ltu));memset(in,false,sizeof(in));memset(pin,-1,sizeof(pin));int min, ptr, i, j;for(i=0; i<maxn; i++){if(!in[page[i]]){//寻找lrumin=1000000; ptr=0;for(j=0; j<size; j++){if(ltu[j]< min){min = ltu[j];ptr = j;}}//替换或写入if(pin[ptr]!=-1)in[pin[ptr]]=false;in[page[i]]=true;pin[ptr]= page[i];fault_n++;ltu[ptr]= ti++;}else//已经在内存里则只需更改最近使用时间{for(j=0; j<size; j++)if(pin[j]== page[i]){ltu[j]= ti++;break;}}}printf("\nBy LRU algorithm, the fault-page number is: %d\n", fault_n);printf(" the hit ratio is : %.2lf\n",(1-(fault_n+0.0)/320.0)); }void OPT_solve(){int ntu[maxp];//next_time_useint fault_n =0;int i, j;memset(in,false,sizeof(in));memset(ntu,-1,sizeof(ntu));//预调页填满int ptr =0;for(i=0; i<maxn && fault_n<size; i++){if(!in[page[i]]){in[page[i]]=true;pin[ptr]= page[i];fault_n++;ptr++;}}//初始化ntu数组ptr =0;for(j=i; j<maxn && ptr<32; j++){if(ntu[page[j]]==-1){ntu[page[j]]= j;ptr++;}}int max;for(; i<maxn; i++){if(!in[page[i]]){max =0;ptr =0;for(j=0; j<size; j++){if(ntu[pin[j]]==-1){ptr = j;break;}if(ntu[pin[j]]> max){max = ntu[pin[j]]; ptr = j;}}in[pin[ptr]]=false;in[page[i]]=true;pin[ptr]= page[i];fault_n++;}ntu[page[i]]=-1;for(j=i+1; j<maxn; j++)if(page[j]== page[i]){ntu[page[i]]= j;break;}}printf("\nBy OPT algorithm, the fault-page number is: %d\n", fault_n);printf(" the hit ratio is : %.2lf\n",(1-(fault_n+0.0)/320.0)); }int main(){srand(time(NULL));welcome();int choice;while(1){input_hint();scanf("%d",&choice);printf("\n");if(choice ==0){printf("BYE-BYE!!!\n");break;}if(choice ==1){produce_inst();turn_page_address();printf("New page address sequence is set OK!!!\n");}else if(choice ==2){printf("Please input the size of memory page number: ");scanf("%d",&size);}else if(choice ==3)FIFO_solve();else if(choice ==4)LRU_solve();else if(choice ==5)OPT_solve();elseprintf("INPUT ERROR !!! \n");}return0;}6.运行结果及分析6.1.运行(以某两次运行结果为例,列表如下:)内存 4 5 10 15 20 25 32 FIFO 285 272 230 178 135 90 32 LRU 285 274 224 185 139 91 32 OPT 221 202 140 96 68 48 32 FIFO 272 262 206 167 128 82 32 LRU 271 265 204 163 130 86 32 OPT 201 183 127 92 66 47 32随着页数的增多,除了FIFO对某些序列会有Belady’s anomaly(详见6.2)外,大部分情况和LRU算法、OPT算法都是缺页率减小。

相关文档
最新文档