操作系统内存管理模拟系统的实现完整版Word文档格式.docx

上传人:b****5 文档编号:21490601 上传时间:2023-01-30 格式:DOCX 页数:36 大小:179.25KB
下载 相关 举报
操作系统内存管理模拟系统的实现完整版Word文档格式.docx_第1页
第1页 / 共36页
操作系统内存管理模拟系统的实现完整版Word文档格式.docx_第2页
第2页 / 共36页
操作系统内存管理模拟系统的实现完整版Word文档格式.docx_第3页
第3页 / 共36页
操作系统内存管理模拟系统的实现完整版Word文档格式.docx_第4页
第4页 / 共36页
操作系统内存管理模拟系统的实现完整版Word文档格式.docx_第5页
第5页 / 共36页
点击查看更多>>
下载资源
资源描述

操作系统内存管理模拟系统的实现完整版Word文档格式.docx

《操作系统内存管理模拟系统的实现完整版Word文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统内存管理模拟系统的实现完整版Word文档格式.docx(36页珍藏版)》请在冰豆网上搜索。

操作系统内存管理模拟系统的实现完整版Word文档格式.docx

进程信息

内存分配

分区创建

进程申请

内存回收

打印分区

低级调度

前后两分区都不是空闲分区

前未空闲后空闲

前空闲后未空闲

前后两分区都是空闲分区

图2.1总体结构流程图

图2.1为总体结构流程图

2.1主程序

主函数既是程序的入口,又是程序的出口,通常我们还可以指定一个exitcode再退出,以表明程序最后的结果是什么样的。

由于主函数肩负着入口和出口的重任,所以最好不要把太多的细节方面的逻辑直接放在主函数内,这样不利于维护和扩展。

主函数应该尽量简洁,具体的实现细节应该封装到被调用的子函数里面去。

此主函数中包括很多功能模块,其中各功能模块用菜单方式选择,为我们提供了九个功能选项。

如图2.1所示

显示一系列功能模块

输入数字,判断数字是否为1—9

根据数字的值调用各功能模块函数

开始

结束

N

Y

图2.1主程序流程图

2.2创建进程模块

进程的创建也就有两种方式:

一是由操作系统创建,二是由父进程创建。

在系统启动时,操作系统会创建一些进程,他们承担着管理和分配系统资源的任务,这些进程通常被称为系统进程。

系统允许一个进程创建新进程,新进程即为子进程,子进程还可以创建新的子进程,形成进程树结构。

此创建进程模块可以输入自己想创建的进程数进而实现进程创建。

如图2.2所示

输入创建进程的个数

初始化进程申请队列

初始化进程分配队列

图2.2创建进程流程图

cout<

<

"

输入进程数目:

;

cin>

>

ProcessNum;

tapplyIndex=newin[ProcessNum];

assignPointer=newint[ProcessNum];

//初始化进程分配队列

maxApplyNum=ProcessNum;

pro=randomCreatPro(ProcessNum);

创建成功

2.3进程信息模块

进程又称任务,是一个动态的使用系统资源、处于活动状态的应用程序。

进程的管理由进程控制块PCB、进程调度、中断管理、任务队列等组成,它是linux文件系统、存储管理、设备管理和驱动程序的基础。

进程控制块PCB中包含了进程的所有信息,主要包括进程PID、进程所占有的内存区域、文件描述符和进程环境等信息。

如图2.3所示

进程是否创建

输出该进程信息

Y

图2.3进程信息流程图

Ifpro==NULL

returnERROR

Forinti=0;

i<

pro++,i++

Ifpro->

status==0

cout<

创建"

elseifpro->

status==1//进程状态

执行"

}elseifpro->

status==-1

status==2

就绪"

status==-2

未就绪"

endl

}

pro-=ProcessNum

创建成功

end

2.4进程申请模块

进程是否被创建

输入申请进程的数目

申请数目是否大于已创建数目

进程申请成功

图2.4进程申请模块图

进程申请模块实现进程申请进入分区,但实现进程申请的进程必须先被创建。

实现根据输入进程申请的个数,判断进程是否可以进入内存,修改进程状态。

申请进程,可以先输入申请进程的数目,进而查看申请进程的信息。

如图2.4所示

ntapplyProcessNum=0;

//每次申请进程数目

ntmaxApplyNum=0;

//最大可申请数目

int*applyIndex=NULL;

//申请进程队列

inttotalApplyNum=0;

//申请总数

int*assignPointer=NULL;

//已分配内存的进程队

2.5分区创建模块

创建分区之前首先要确定准备创建的分区类型。

有三种分区类型,它们是“主分区”、“扩展分区”和“逻辑分区”。

主分区是指直接建立在硬盘上、一般用于安装及启动操作系统的分区。

由于分区表的限制,一个硬盘上最多只能建立四个主分区,或三个主分区和一个扩展分区;

扩展分区是指专门用于包含逻辑分区的一种特殊主分区。

可以在扩展分区内建立若干个逻辑分区;

逻辑分区是指建立于扩展分区内部的分区。

没有数量限制。

如图2.5所示

随机分配内存大小

创建分区

图2.5分区创建模块流程图

begin

Nodep

if(head==NULL){

Cout分区未创建,请先创建分区ndl

else

p=head->

next

cout.fill('

'

Whilep!

=NULL

cout.width(3)

cout分区的大小

p=p->

next;

}

return创建成功

2.6内存分配模块

常见内存分配算法如下:

首次适应算法,从空闲分区链首开始查找。

循环适应算法,从上次找到的空闲分区开始查找。

最佳适应算法,是最小的空闲分区分配给作业。

最差适应算法,最差适应算法中,该算法按大小递减的顺序形成空闲区链,内存分配,第一次分配,从头结点开始,其他重上次分配的节点开始,然后从分配资源的进程开始分配,若分配的进程进已分配进程队列,则申请进程的偏移指针回首址,修改分配数。

如图2.6所示

伪代码

Nodep=head->

返回最大空闲结点

计数count

if(p==NULL)则

cout空闲链表不存在

否则do{

if(p->

status==0)则

Cout++

if(count==1)则p=q

否则if(p->

subarea.subareaSize>

q->

subarea.subareaSize)

该分区空闲吗?

分区长>

=SIZE?

度>

将状态位置为正在使用

返回分区号

取下一表项

选择所要的适应算法

要求按SIZE大小分区

取分区说明表第一项

表结束吗?

无法分配

图2.6内存分配模块流程图

2.7低级调度模块

低级调度又称为进程调度、短程调度,它决定就绪队列中的哪个进程将获得处理机,然后由分派程序执行把处理机分配给该进程的操作。

在批处理,分时,实时三类系统中,进程调度必须被配置,因而是一种最基本的调度。

与中级调度——交换,高级调度——作业调度相对应。

低级调度的功能:

保存处理机的现场信息。

按某种算法选取进程。

把处理器分配给进程。

如图2.7所示

是否存在已分配好资源的进程

选择一个就绪进程进入CPU

CPU正在调度

进程获得处理机,开始执行

图2.7低级调度模块流程图

Displayprocess()

Createlinklist()

Creatprocess()

Assignmemory()

Display()

Callbackmemory()

Main()

3函数关系调用图

如图3.1所示,为函数关系调用图,主函数main()调用其他九个模块,Cowattemper()调用Displyprocess(),Creatprocess()调用Randomcreatpro()总体结构流程如下图所示。

Cowattemper()

Applyforprocess()

Menu()

Randomcrearpro()

4测试结果

所谓程序调试是指对程序的查错与排错。

在编写完一个源程序之后,不要立即进行编译,而应对程序进行全面的人工检查一遍,检查无误后可以开始进行程序调试。

由编译系统进行检查、发现错误,根据编译系统提示的错误类型和警告及出现的位置,我们可以定位到错误地点进行修改,然后再编译,如此反复进行,直至不再出现错误位置,最后才进行程序的连接于运行调试完以后,下一步就是对程序进行测试,运行程序,向程序中输入数据,根据输出结果是否正确(是否符合自己的想法)来判断程序是否正确,如果不正确或不符合自己的目的,就需要对程序进行修改。

然后再调试,再测试,直至结果无误或符合要求后,测试才算结束,此时,程序才算是满足题目要求的正确程序。

4.1主界面调试结果

主界面调试结果是运行程序后出现的主界面,它包括了内存管理中的一系列应用,它主要包括,创建进程,进程信息,进程申请,分区创建,内存分配,内存回收,打印分区,低级调度等应用,我们可以选择1-9的数字进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.1主界面调试结果图

4.2创建进程调试结果

创建进程运行结果,我们可以根据主界面显示结果,选择数字1,进而进行创建进程,创建进程时,需要你先输入想要创建进程的数目,然后再创建进程。

其中创建的进程里面包括进程的大小和其运行状态。

如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.2创建进程调试结果图

4.3进程信息调试结果

进程信息调试结果。

我们可以根据主界面显示结果,选择数字2,进而可以查看进程的信息,进程的信息里面包括所创建进程的大小和进程的状态。

如果我们选择1和3-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.3进程信息调试结果图

4.4进程申请调试结果

进程申请调试结果,我们可以根据主界面显示结果,选择数字3,然后根据主界面的提示输入所要申请进程的数目,如果输入的申请进程的数目大于所创建进程的数目,则退出提示重新输入申请进程的数目。

然后再根据申请数目输入所要申请的进程,申请成功之后退出到主界面。

如果我们选择1,2和4-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.4进程申请调试结果图

4.5分区创建调试结果

分区创建调试结果,我们可以根据主界面显示结果,选择数字4,然后进程随机分配内存的大小,进而创建分区。

如果我们选择1,2,3和5-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.5分区创建调试结果图

4.6内存分配调试结果

内存分配调试结果,我们可以根据主界面显示结果,选择数字5,然后根据程序中所输入的内存分配算法:

首次适应算法,循环适应算法,最佳适应算法和最坏适应算法中选择其中一种分配算法,然后进行内存的分配。

如果我们选择1-4和6-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.6内存分配调试结果图

4.7内存回收调试结果

内存回收调试结果,我们可以根据主界面显示结果,选择数字6,然后调试结果就会显示正在执行的进程数,以及正在执行进程的大小和分配的分区号。

然后程序会提示你是否结束进程,如果选择是,程序调试将会继续显示主界面,如果选择否,程序调试会直接退出。

如果我们选择1-5和7-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.7内存回收调试结果图

4.8打印分区调试结果

打印分区调试结果,我们可以根据主界面显示结果,选择数字7,然后程序调试就会显示分区的大小,分区的开始地址以及此分区是否空闲等信息。

程序自动会进行分区的打印。

如果我们选择1-6和8-9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.8打印分区调试结果图

4.9低级调度调试结果

低级调度调试结果,我们可以根据主界面显示结果,选择数字8,然后运行界面就会显示所创建进程的信息,然后我们可以选择所创建进程中的一个就绪进程进入cpu,然后cpu进行调度,最后获得处理机进行低级调度的执行。

如果我们选择1-7和9的数字则进行相应的操作,如果写入除1-9以外的数字,程序运行将自动退出,不再运行。

图4.9低级调度调试结果图

5源程序

#include<

iostream>

cmath>

iomanip.h>

time.h>

#defineSize4

#definenum10

#defineSUCCESS1

#defineERROR-1

typedefintbyte;

typedefstruct{

bytesubareaSize;

//分区大小

intstartLoc;

//起始地址

intindex;

//分区号

}SubareaTable;

//分区表

typedefstructnode{//结点

SubareaTablesubarea;

//分区

structnode*next;

intstatus;

//状态位0(空闲)1(使用)

}*Node,*LinkList;

byteprocessSize;

intsubareaIndex;

//保存分区号

//进程状态,0(新建)1(执行)-1(终止)-2(未绪。

申请但没有分配内存)2(就绪,已分配内存)

}Process;

//进程

intsubareaSize[num]={8,12,16,32,24,16,64,128,40,64};

Process*pro=NULL;

//保持进程信息

intProcessNum=0;

//进程数目

intapplyProcessNum=0;

intmaxApplyNum=0;

//已分配内存的进程队列

intassignFlag=0;

//分配索引,表示已申请队列已分配的进程数

intexeIndex;

//执行的进程号

Node*subareaNode=newNode[3];

//分区回收时,进程所在分区及其前,后分区信息

LinkListcreateLinkList(intn);

//建立空闲分区链

NodefirstFit(LinkList&

head,Processpro);

//首次适应算法

NodenestFit(LinkList&

head,Processpro,Nodeflag);

//循环适应算法

NodebestFit(LinkList&

//最佳适应算法

NodeworstFit(LinkList&

//最坏适应算法

Nodeassign(LinkList&

head,intorderIndex,intindex,NodeflagNode);

//一次分区分配

intassignMemory(LinkList&

head);

//内存分配

voidinsertNode(LinkList&

head,Nodeq,intindex);

//插入节点

NodedeleteNode(LinkList&

head,intindex);

//删除节点

intdisplay(LinkList&

//打印分区分配情况

intlowAttemper(int*excursionPointer);

//低级调度

intfindSubarea(LinkList&

//回收内存

intmenu();

//菜单

intcreatProcess();

//创建进程

Process*randomCreatPro(intn);

//随机产生进程

LinkListcreateLinkList(intn){//建立空闲分区链

-------------创建分区--------------"

endl;

LinkListhead;

Nodep;

head=(LinkList)malloc(sizeof(node));

头结点分配错误"

returnNULL;

}

head->

next=NULL;

//链表尾巴设置为NULL

LinkListq=head;

intstart=0;

for(inti=1;

=n;

i++){

p=(Node)malloc(sizeof(node));

if(p==NULL){

节点分配错误"

p->

next=q->

q->

next=p;

q=p;

subarea.index=i;

subarea.subareaSize=subareaSize[i-1];

//分区表赋值大小

subarea.startLoc=start;

status=0;

start+=subareaSize[i-1];

分区创建成功!

!

returnhead;

head,Processpro){//首次适应算法

Nodep=head->

//遍历结点,返回结点,从第一个结点开始遍历

空闲链表不存在"

else{

do{

if(p->

status==0&

&

p->

=pro.processSize){

break;

while(p!

=NULL);

if(p==NULL){//没找到合适的结点

returnp;

head,Processpro,Nodeflag){//循环适应算法

Nodep=flag->

//遍历结点

while(p!

=NULL){

if(p==NULL){//遍历到链表结尾

p=head;

//从头开始遍历

=flag){//标记结点

if(p==flag){//正常跳出循环,没有合适的结点可分配

}else{

//在flag结点前找到一合适的结点分配

}else{

//在flag结点后找到一合适的结点分配

head,Processpro){//最佳适应算法

Nodeq;

//返回最佳空闲结点

intleave;

//剩余空间

intcount=0;

//计数器

do{

=pro.processSize){

count++;

if(count==1){//第一个可以分配的空闲分区

leave=p->

subarea.subareaSize-pro.processSize;

}elseif(count>

1){

subarea.subareaSize-pro.pro

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 总结汇报 > 工作总结汇报

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1