动态可变分区存储管理模拟系统
3用C语言模拟实现可变式分区存储管理
3用C语言模拟实现可变式分区存储管理可变式分区存储管理是一种动态分配内存空间的方式,它能够根据进程的内存需求来动态地分配和回收内存空间,提高内存的利用率。
在C语言中,我们可以使用指针和数据结构来模拟实现可变式分区存储管理。
1.使用结构体来表示内存块首先,我们可以定义一个结构体来表示每个内存块的属性,包括起始地址、大小、以及是否被占用等信息。
```cstruct Blockint start_address;int size;int is_allocated; // 0代表未分配,1代表已分配};```2.初始化内存空间接下来,我们可以定义一个数组来表示整个内存空间,该数组的每个元素都是一个 Block 结构体,表示一个内存块。
在程序开始时,我们可以初始化一个 Block 数组,表示整个内存空间的初始状态。
```c#define TOTAL_SIZE 1024 // 内存总大小struct Block memory[TOTAL_SIZE];void init_memormemory[0].start_address = 0;memory[0].size = TOTAL_SIZE;memory[0].is_allocated = 0;```3.分配内存空间当进程需要分配内存空间时,可变式分区存储管理会选择一个合适的内存块来分配给该进程。
我们可以定义一个函数来实现分配内存的过程。
```cint allocate_memory(int size)int i;for (i = 0; i < TOTAL_SIZE; i++)if (!memory[i].is_allocated && memory[i].size >= size)//找到未分配且大小足够的内存块memory[i].is_allocated = 1;memory[i].size -= size;return memory[i].start_address;}}//没有找到合适的内存块return -1;```4.回收内存空间当进程释放已分配的内存空间时,我们需要回收这部分内存,使其变为未分配状态。
动态分区分配方式的模拟
动态分区分配方式的模拟动态分区分配方式是计算机中内存管理的一种重要方式。
在动态分区分配方式中,内存空间被分割为多个不同大小的分区,每个分区可以被进程占用。
当一个进程需要内存时,系统会为其分配一个适当大小的分区,进程结束后,该分区将会被释放出来供其他进程使用。
为了更好地理解动态分区分配方式的原理和实际运作,可以通过模拟的方法来观察和分析。
下面是一个简单的动态分区分配方式的模拟过程:假设我们有一块容量为6400KB的内存,要模拟分配4个进程的情况。
这4个进程的内存需求分别是1000KB,2000KB,500KB和300KB。
首先,我们可以将内存划分为几个分区,每个分区的大小根据需要进行调整。
可以设置整块内存为一块分区(大小为6400KB),或者划分成多个较小的分区。
由于这里有4个进程需要分配内存,我们可以为它们设置4个分区,分别为P1,P2,P3和P41.初始状态:内存:[6400KB](未分配)进程:P1,P2,P3,P4(空)2.分配P1:内存:[1000KB](P1)、[5400KB](未分配)进程:P1,P2,P3,P4P1占用了1000KB的内存,剩余空间为5400KB。
3.分配P2:内存:[1000KB](P1)、[2000KB](P2)、[3400KB](未分配)进程:P1,P2,P3,P4P2占用了2000KB的内存,剩余空间为3400KB。
4.分配P3:内存:[1000KB](P1)、[2000KB](P2)、[500KB](P3)、[2900KB](未分配)进程:P1,P2,P3,P4P3占用了500KB的内存,剩余空间为2900KB。
5.分配P4:内存:[1000KB](P1)、[2000KB](P2)、[500KB](P3)、[300KB](P4)、[2600KB](未分配)进程:P1,P2,P3,P4P4占用了300KB的内存,剩余空间为2600KB。
在模拟的过程中,我们可以看到进程在内存中的分配情况和未分配内存的变化。
操作系统c语言设计程序模拟内存的动态分区内存管理方法。内存分区使用分区(说明)
操作系统c语言设计程序模拟内存的动态分区内存管理方法。
内存分区使用分区(说明)摘要:1.引言2.内存动态分区原理a.内存分区类型b.内存分区算法3.C语言实现内存动态分区管理a.内存分配函数b.内存释放函数c.内存管理函数4.内存动态分区管理的应用a.进程管理b.文件系统5.内存分区管理的优化a.算法改进b.硬件支持6.结论正文:【引言】内存管理是操作系统中的核心功能之一,它负责对系统内存进行有效分配、管理和回收。
在众多内存管理方法中,动态分区管理因其灵活性和高效性而得到了广泛应用。
本文将介绍操作系统中动态分区管理的原理,以及如何使用C语言实现这一管理方法。
【内存动态分区原理】内存动态分区管理主要包括两个方面:内存分区类型和内存分区算法。
a.内存分区类型内存分区通常分为两类:固定大小分区和不固定大小分区。
固定大小分区是指内存中被分配成固定大小的分区,适用于内存需求稳定的场景。
不固定大小分区则根据实际需求进行分配,更加灵活。
b.内存分区算法内存分区算法主要包括首次适应算法(FF)、最佳适应算法(BF)、最坏适应算法(WF)等。
首次适应算法简单、快速分配,但可能导致内存碎片;最佳适应算法尽量使用最小空间满足需求;最坏适应算法则优先使用大内存块,分割后空闲块仍较大。
【C语言实现内存动态分区管理】在C语言中,我们可以通过编写内存分配函数、内存释放函数和内存管理函数来实现内存动态分区管理。
a.内存分配函数内存分配函数负责根据用户请求分配内存。
可以根据内存分区类型和内存分区算法实现。
例如,首次适应算法可以遍历空闲内存块表,找到第一个满足需求的空闲块并进行分配。
b.内存释放函数内存释放函数负责回收不再使用的内存块,将其归还给空闲内存池。
释放内存时,需要确保该内存块之后的内存块不会被误用。
c.内存管理函数内存管理函数负责监控内存使用情况,如内存总量、空闲内存块数量等,以便在必要时进行内存扩容或压缩。
【内存动态分区管理的应用】内存动态分区管理在操作系统中有着广泛应用,如进程管理和文件系统等。
动态分区分配存储管理系统
动态分区分配存储管理系统学院专业学号学生姓名指导教师姓名2014年3月20 日目录1设计目的------------------------------------------------------3 2设计内容------------------------------------------------------3 3设计要求------------------------------------------------------3 4程序总体功能说明---------------------------------------------3 5程序各模块功能说明-------------------------------------------4 6程序设计流程图------------------------------------------------5 7系统测试------------------------------------------------------8 8程序代码-----------------------------------------------------19 9课设总结-----------------------------------------------------34一、设计目的操作系统课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会。
●进一步巩固和复习操作系统的基础知识。
●培养学生结构化程序、模块化程序设计的方法和能力。
●提高学生调试程序的技巧和软件设计的能力。
●提高学生分析问题、解决问题以及综合利用 C 语言进行程序设计的能力。
二、设计内容用高级语言编写和调试一个动态分区内存分配程序,演示实现下列两种动态分区分配算法1.首次适应算法2.循环首次适应算法三、设计要求1.内存中有0-100M 的空间为用户程序空间,最开始用户空间是空闲的2.作业数量、作业大小、进入内存时间、运行时间需要通过界面进行输入3.可读取样例数据(要求存放在外部文件中)进行作业数量、作业大小、进入内存时间、运行时间的初始化4.根据作业进入内存的时间,采用简单的先进先出原则进行从外存到内存的调度,作业具有等待(从外存进入内存执行)、装入(在内存可执行)、结束(运行结束,退出内存)三种状态。
模拟实现可变分区存储管理
《操作系统》课程设计说明书题目:模拟实现可变分区存储管理班级:学号:姓名:指导老师:1.目的和要求在熟练掌握计算机分区存储管理方式的原理的基础上,利用一种程序设计语言模拟实现操作系统的可变分区存储管理的功能,一方面加深对原理的理解,另一方面提高学生通过编程根据已有原理解决实际问题的能力,为学生将来进行系统软件开发和针对实际问题提出高效的软件解决方案打下基础。
2.设计内容设计合理的数据结构来描述存储空间:对于未分配出去的部分,可以用空闲分区队列或空闲分区链表来描述,对于已经分配出去的部分,由装入内存的作业占据,可以将作业组织成链表或数组。
实现分区存储管理的内存分配功能,实现两种适应算法:首次适应算法,最坏适应算法。
实现分区存储管理的内存回收算法:要求能够正确处理回收分区与空闲分区的四种邻接关系。
当碎片产生时,能够进行碎片的拼接。
3.设计环境Windows操作系统、DEV C++C语言4.程序概要(1)数据结构和全局变量int type = 0; //算法类型//空闲分区struct freelink {int len; //len为分区长度int address; //address为分区起始地址struct freelink *next;};//占用分区struct busylink {char name; //作业或进程名,name='S' 表示OS占用int len;int address;struct busylink *next;};struct freelink *free_head = NULL; //自由链队首指针struct busylink *busy_head = NULL, //占用区队首指针*busy_tail = NULL; //占用区队尾指针(2)功能模块划分大体上可以将整个程序的模块划分成如下几个部分:1)主模块:主要是初始化(设置物理内存的用户区的大小,选取适应算法)和界面,界面参考如下:2)内存分配算法(实现两种适应算法:最坏适应算法,首次适应算法)3)内存回收算法(考虑四种邻接情况,尤其是采用最佳(坏)适应算法时的分区合并)4)碎片拼接算法5)空闲分区队列显示6)占用分区队列显示(3)各函数调用关系(4)主要函数流程图allocateMemoByWF();//两种算法分配回收大致相同,在这里只列举一种compactMemo()freeMemoByWF()5. 源代码#include <stdio.h>#include <stdlib.h>#define MAX_SIZE 512 //系统能分配的最大内存#define FALSE 0#define TRUE 1int type = 0; //算法类型//空闲分区struct freelink {int len; //len为分区长度int address; //address为分区起始地址struct freelink *next;};//占用分区struct busylink {char name; //作业或进程名,name='S' 表示OS占用int len;int address;struct busylink *next;};struct freelink *free_head = NULL; //自由链队列(带头结点)队首指针struct busylink *busy_head = NULL, //占用区队列队(带头结点)首指针*busy_tail = NULL; //占用区队列队尾指针//初始化void init() {struct freelink *p;struct busylink *q;free_head = (struct freelink*)malloc(sizeof(struct freelink));free_head->next = NULL; // 创建自由链头结点busy_head = busy_tail = (struct busylink*)malloc(sizeof(struct busylink));busy_head->next = NULL; // 创建占用链头结点p = (struct freelink *)malloc(sizeof(struct freelink));p->address = 64;p->len = MAX_SIZE - 64; //(OS占用了64K)p->next = NULL;free_head->next = p;q = (struct busylink *)malloc(sizeof(struct busylink));q->name = 'S'; //S表示操作系统占用q->len = 64;q->address = 0;q->next = NULL;busy_head->next = q;busy_tail = q;}//紧凑struct freelink* compactMemo(int require) {int sum = 0;struct freelink *fNode = free_head->next;while (fNode != NULL) {sum += fNode->len;fNode = fNode->next;}printf("\n");if (sum < require) {return NULL;}//删除空闲区所有节点struct freelink *p = free_head->next; //让p一直指向第一个数据节点while (p != NULL) {free_head->next = p->next;free(p);p = free_head->next;}//创建新的分区struct freelink *node = (struct freelink*)malloc(sizeof(struct freelink));node->address = 0;node->len = MAX_SIZE;free_head->next = node;node->next = NULL;//修改占用区作业内存地址struct busylink *q = busy_head->next;while (q != NULL) {q->address = node->address;node->len -= q->len;node->address += q->len;q = q->next;}return node;}//最坏(佳)适应算法在分区合并和分割后需要调整分区位置int adjust(struct freelink *node) {struct freelink *p = free_head;//合并后链表中只剩一个分区if (p->next == NULL) {free_head->next = node;node->next = NULL;return TRUE;}while (p->next != NULL && node->len <= p->next->len) { p = p->next;}if (p->next == NULL) {p->next = node;node->next = NULL;}else {node->next = p->next;p->next = node;}return TRUE;}//最坏适应算法int allocateMemoByWF() {int require;printf("请输入作业所需内存大小:");scanf("%d", &require);//判断第一个空闲分区大小是否满足需求struct freelink *p = free_head->next;if (p->len < require) {printf("没有分区满足要求,正在尝试碎片拼接...\n");//判断所有分区容量总和是否满足要求if ((p = compactMemo(require)) == NULL) {return FALSE;}}//将第一个空闲分区切割require分配给该作业struct busylink *q = (struct busylink *)malloc(sizeof(struct busylink));printf("请输入作业名称:");getchar(); //输入require之后有一个换行符,用getchar吃掉scanf("%c", &q->name);//检查是否重名struct busylink *temp = busy_head->next;while (temp != NULL && temp->name != q->name) {temp = temp->next;}if (temp != NULL) {printf("该作业名已存在!\n");return FALSE;}q->len = require;q->address = p->address;q->next = NULL;//将作业按地址递增的顺序插入到作业队列中temp = busy_head;while(temp->next != NULL && q->address > temp->next->address) { temp = temp->next;}if (temp->next == NULL) {temp->next = q;q->next = NULL;}else {q->next = temp->next;temp->next = q;}//分割空闲分区if (p->len == require) {free(p);return TRUE;}else {p->address += require;p->len -= require;}//把第一个分区从空闲区中拿出来if (p->next != NULL) {free_head->next = p->next;}else return TRUE; //空闲队列中是否只存在一个节点//将分割后的分区放到合适的位置adjust(p);return TRUE;}//首次适应算法int allocateMemoByFF() {int require;printf("请输入作业所需内存大小:");scanf("%d", &require);struct freelink *p = free_head->next;struct freelink *pre = free_head;while (p != NULL && p->len < require) {pre = p;p = p->next;}if (p == NULL) {printf("没有分区满足要求,正在尝试碎片拼接...\n");//判断所有分区容量总和是否满足要求if ((p = compactMemo(require)) == NULL) {return FALSE;}}//将第一个满足条件的分区分割合适的内存分配给作业struct busylink *q = (struct busylink *)malloc(sizeof(struct busylink));printf("请输入作业名称:");getchar(); //输入require之后有一个换行符,用getchar吃掉scanf("%c", &q->name);//检查是否重名struct busylink *temp = busy_head->next;while (temp != NULL && temp->name != q->name) {temp = temp->next;}if (temp != NULL) {printf("该作业名已存在!\n");return FALSE;}q->len = require;q->address = p->address;q->next = NULL;//将作业按地址递增的顺序插入到作业队列中temp = busy_head;while(temp->next != NULL && q->address > temp->next->address) { temp = temp->next;}if (temp->next == NULL) {temp->next = q;q->next = NULL;}else {q->next = temp->next;temp->next = q;}//分割空闲分区if (p->len == require) {pre->next = p->next;free(p);return TRUE;}else {p->address += require;p->len -= require;return TRUE;}}//匹配节点并创建回收分区struct freelink* matchName(char name) {struct busylink *q = busy_head;struct freelink *node = (struct freelink *)malloc(sizeof(struct freelink));//找到匹配节点的前一个while (q->next != NULL && q->next->name != name) {q = q->next;}if (q->next == NULL) {printf("%c进程不存在\n",name);return NULL;}//接收匹配节点的内存信息node->len = q->next->len;node->address = q->next->address;//在占用分区中删除匹配的节点struct busylink *temp = q->next;if (q->next == busy_tail) {busy_tail = q;q->next = NULL;}else {q->next = q->next->next;}free(temp);return node;}int freeMemoByWF() {printf("请输入作业名称:");char name;getchar();scanf("%c", &name);printf("\n");//将内存(即node节点)放回空闲区struct freelink *node;if ((node = matchName(name)) == NULL) {return FALSE;}struct freelink *p = free_head->next;struct freelink *pre = free_head;//三种邻接情况(合并后需要重新根据大小排序)while (p != NULL) {//与下一分区邻接if (node->address + node->len == p->address) {//与上一分区邻接if (p->next != NULL&&p->next->address + p->next->len == node->address) {struct freelink* temp = p->next;temp->len = temp->len + p->len + node->len;free(node);pre->next = temp->next;free(p);adjust(temp);printf("回收成功!\n");return TRUE;}else {p->address = node->address;p->len += node->len;free(node);pre->next = p->next; //把合并后分区取出来adjust(p);printf("回收成功!\n");return TRUE;}}//与上一分区邻接if (p->address + p->len == node->address) {//同时与下一分区邻接if (p->next != NULL &&node->address + node->len == p->next->address) {p->len = p->len + node->len + p->next->len;pre->next = p->next->next;free(p->next);free(node);adjust(p);printf("回收成功!\n");return TRUE;}else {p->len += node->len;free(node);pre->next = p->next;adjust(p);printf("回收成功!\n");return TRUE;}}pre = p;p = p->next;}//不邻接adjust(node);printf("回收成功!\n");return TRUE;}int freeMemoByFF() {printf("请输入作业名称:");char name;getchar();scanf("%c", &name);printf("\n");//将内存(node节点)放回空闲区struct freelink *node;if ((node = matchName(name)) == FALSE) {return FALSE;}struct freelink *p = free_head->next;//三种邻接情况while (p != NULL) {//与下一分区邻接if (node->address + node->len == p->address) {p->address = node->address;p->len += node->len;free(node);printf("回收成功!\n");return TRUE;}//与上一分区邻接if (p->address + p->len == node->address) {//同时与下一分区邻接if (p->next != NULL &&node->address + node->len == p->next->address) {p->len = p->len + node->len + p->next->len;struct freelink* temp = p->next;p->next = p->next->next;free(temp);free(node);printf("回收成功!\n");return TRUE;}else {p->len += node->len;free(node);printf("回收成功!\n");return TRUE;}}p = p->next;}//不邻接p = free_head;while (p->next != NULL && node->address > p->next->address) { p = p->next;}if (p->next == NULL) {p->next = node;node->next = NULL;}/*回收分区是分区链中地址最大的一个*/else {node->next = p->next;p->next = node;}printf("回收成功!\n");return TRUE;}//输出空闲分区void printFreeLink() {struct freelink *p = free_head->next;printf("空闲分区:\n");while (p != NULL) {printf("分区起始地址:%d ", p->address);printf("分区大小:%d\n", p->len);p = p->next;}printf("\n");}//输出占用分区void printBusyLink() {struct busylink *q = busy_head->next;printf("占用分区:\n");while (q != NULL) {printf("进程名:%c ", q->name);printf("起始地址:%d ", q->address);printf("占用内存大小:%d\n", q->len);q = q->next;}printf("\n");}void WF() {while(1) {printf("----------------------------------------------------------------\n");printf("1. 初始化\n\n");printf("2. 作业进入内存\n\n");printf("3. 作业完成\n\n");printf("4. 显示当前自由分区\n\n");printf("5. 显示当前作业占用分区\n\n");printf("6. 退出\n");printf("----------------------------------------------------------------\n");int m;scanf("%d", &m);printf("\n");switch(m) {case 1: init(); break;case 2: allocateMemoByWF(); break;case 3: freeMemoByWF(); break;case 4: printFreeLink(); break;case 5: printBusyLink(); break;case 6: return;}}}void FF() {while(1) {printf("----------------------------------------------------------------\n");printf("1. 初始化\n\n");printf("2. 作业进入内存\n\n");printf("3. 作业完成\n\n");printf("4. 显示当前自由分区\n\n");printf("5. 显示当前作业占用分区\n\n");printf("6. 退出\n");printf("----------------------------------------------------------------\n");int m;scanf("%d", &m);printf("\n");switch(m) {case 1: init(); break;case 2: allocateMemoByFF(); break;case 3: freeMemoByFF(); break;case 4: printFreeLink(); break;case 5: printBusyLink(); break;case 6: return;}}}int main() {while(1) {printf("----------------------------------------------------------------\n");printf("1. 首次适应算法\n\n");printf("2. 最坏适应算法\n\n");printf("3. 退出\n");printf("----------------------------------------------------------------\n");int m;scanf("%d", &m);printf("\n");switch(m) {case 1: FF(); break;case 2: WF(); break;case 3: exit(0);}}}6. 实验结果:1.最坏适应算法:A(16), B(32), C(64), D(128)分配(成功):分配失败(重名):当前空闲区和占用区情况:free(A)//不邻接回收成功:回收失败(不存在该进程):当前空闲区和占用区情况:free(C)当前空闲区情况:free(B)//与上下分区邻接当前空闲区情况:E(100)当前空闲区情况:F(200)没有分区满足时尝试碎片拼接当前空闲区和占用区情况:最坏适应算法有一种情况:A(40), B(50), C(60), D(50)free(A), free(C)与首次适应分配不同,最坏适应算法可能高地址在低地址前free(B)2. 首次适应算法:A(16), B(32), C(64), D(128),E(10),F(5),free(F)free(A), free(C)free(B)G(200)在分配内存过程中,将作业加入到占用队列时是按地址递增的顺序排列,保证了拼凑算法后各作业的相对位置不变化7. 实验总结:a)以前对链表操作有一些误操作,比如排序时,一般使用冒泡法。
计算机操作系统课程设计报告《存储管理——动态分区分配算法的模拟》
《计算机操作系统》课程设计题目:—存储管理一一动态分区分配算法的模拟 _专业: _________ 软件工程_______________年级: __________ 2012级 ___________小组成员:_____________________________ 指导教师:______________________________ 时间:________________________________地点:________________________________2012年5月目录目录 (1)概述 (3)2. ................................................................................................................................ 课程设计任务及要求. (3)2.1 设计任务 (3)2.2 设计要求 (3)2.3 课程设计任务安排 (3)3. 算法及数据结构 (4)3.1 算法的总体思想(流程) (4)3.2 首次适应算法 (4)3.2.1 功能 (4)3.2.2 数据结构(包括变量的定义,要注释!) (4)323算法(流程图表示,或伪C表示) (5)3.3 循环首次适应算法 (6)3.3.1 功能 (6)3.3.2 数据结构 (6)3.3.3 算法 (7)3.4 最佳适应算法 (8)3.4.1 功能 (8)3.4.2 数据结构 (8)3.4.3 算法 (8)3.5 最坏适应算法 (10)3.5.1 功能 (10)3.5.2 数据结构 (10)3.5.3 算法 (11)4. 程序设计与实现 (12)4.1 程序流程图 (12)4.2 程序代码(要注释) (12)4.3 实验结果 (21)5. 结论 (23)6. 收获、体会和建议。
(23)A的总结: (23)B的总结: (23)7. 参考文献。
操作系统c语言设计程序模拟内存的动态分区内存管理方法.内存分区使用分区(说明)表
操作系统c语言设计程序模拟内存的动态分区内存管理方法.内存分区使用分区(说明)表1. 引言1.1 概述在计算机科学领域,内存管理是操作系统中至关重要的一个组成部分。
操作系统需要负责对内存资源进行合理的分配和释放,确保程序能够顺利执行,并且不会发生内存泄漏等问题。
本篇文章将介绍一种基于C语言设计程序模拟内存的动态分区内存管理方法。
该方法通过使用分区表来对内存空间进行动态管理。
我们将详细探讨这种方法的实现步骤、技巧以及性能评估和案例分析结果。
1.2 文章结构本文主要分为五个部分:引言、动态分区内存管理方法、C语言设计程序模拟内存的实现步骤与技巧、程序模拟内存动态分区内存管理方法性能评估和案例分析,以及结论与展望。
在引言部分,我们将首先介绍本文的概述,即主题和目标。
然后简要说明文章的结构,以便读者更好地理解全文内容。
1.3 目的本文旨在介绍一种使用C语言设计程序模拟内存的动态分区内存管理方法,并探讨该方法在实际应用中可能遇到的问题和优化建议。
我们希望通过本文的阐述,读者可以对动态分区内存管理方法有更深入的理解,并能够在实际项目中应用相关技术和知识。
通过对程序模拟动态分区内存管理方法进行性能评估和案例分析,我们也旨在为读者提供一个参考,帮助他们更好地理解该方法的优缺点,并从中获得一些有价值的启示。
总之,本文将为读者提供一种全面而深入的了解动态分区内存管理方法的途径,并希望能够激发读者们对内存管理领域研究的兴趣。
2. 动态分区内存管理方法2.1 内存管理概述在操作系统中,内存管理是一个关键的部分。
动态分区内存管理方法是一种常用的内存分配技术,它将可用的内存空间划分为多个不同大小的动态分区,以便满足不同程序对内存空间的需求。
2.2 动态分区内存管理算法原理动态分区内存管理算法主要包括三种:首次适应算法、最佳适应算法和最坏适应算法。
首次适应算法是指从空闲列表中选择第一个能满足所需内存大小的空闲块进行分配。
这种算法简单直观,但可能会产生较大的碎片化问题。
实验三 可变分区存储管理
实验三可变分区存储管理一、实验目的通过可变分区存储模拟系统,掌握可变分区存储管理的基本原理,分区的分配与回收过程。
二、实验原理1.动态分区分配:是根据进程的实际需求,动态地为之分配内存空间在连续分配方式中,必须把一个系统或用户程序装入一连续的内存空间。
如果在系统中只有若干小的分区,即使它们容量的总和大于要装入的程序,但由于这些分区不相邻接,也无法把改程序装入内存。
2.紧凑:通过移动内存中作业的位置,以把原来多个分散的小分区拼接成一个大分区的方法。
三、实验内容与步骤1.打开程序,所得程序界面窗口如图3-1:图3-12.首先选择算法:是否使用搬家算法,可以通过界面上的按钮或算法菜单栏进行选择;如果不先选择算法,其他功能将被隐藏;注意:在程序执行过程中,不可以重新选择算法。
3.进行初始化:设置内存大小,可以选择默认值400KB;确定内存大小前,其他操作将被屏蔽。
4.初始化内存大小以后,就可以进行添加进程操作。
5.添加一个进程后,撤消进程功能被激活,可以撤消一个选定的进程或所有的进程(图3-2)图3-26.查询功能:可以通过按钮或菜单栏显示内存状态图形、空闲区图表,还可以在内存状态条里闪烁显示某一在空闲区图表选中的空闲区。
7.内存不足但经过搬家算法可以分配内存空间给进程,将有如下(图3-3)提示:图3-38.内存空间不足也有相应提示。
9.重置或退出。
四、实验结果第一组数据:内存大小300K,三个进程分配情况为:60K,50K,80K,不采用搬家算法第二组数据:内存大小500K,五个进程分配情况为:60K,80K,20K,70K,300K,不采用搬家算法第三组数据:内存大小400K,6个进程分配情况为:30K,90K,20K,50K,70K,80K,分配好以后删除第三个,第五个进程,再为第七个进程分配100K,不采用搬家算法第四组数据:内存大小300K,三个进程分配情况为:60K,50K,80K,采用搬家算法第五组数据:内存大小500K,五个进程分配情况为:60K,80K,20K,70K,300K,采用搬家算法第六组数据:内存大小400K,6个进程分配情况为:30K,90K,20K,50K,70K,80K,分配好以后删除第三个,第五个进程,再为第七个进程分配100K,采用搬家算法第七组数据大家自行设计,不采用搬家算法,但不能全部分配第八组数据与第七组数据相同,但采用搬家算法后可以全部分配。
操作系统可变分区存储管理模拟
操作系统实验(三)可变分区存储管理模拟实验作者:顾熙杰准考证号:4报到号:177实验地点:浙工大计算机中心1)实验目的理解操作系统中可变分区管理的算法,掌握分配和回收算法掌握空闲分区的合并方法掌握不同的适应算法2)实验内容建立数据结构建立空闲分区队列根据不同的适应算法建立队列编写分配算法编写回收算法3)数据结构'分区首地址'分区长度'分区状态-1表示不存在,0表示空闲分区,1表示已经分配的分区'该分区正在活动的进程代号4)程序流程图面向对象程序设计由事件驱动,画流程图比较困难。
(1)分配新的分区最先适应按地址找最优适应,找最小可以满足的最坏适应,找最大可以满足的(2)分区回收既无上邻又无下邻既有上邻又有下邻只有上邻只有下邻5)实验中需要改进的地方由于没有使用链表,程序结构比较混乱,需要大大改进,提高可阅读性。
6)程序代码()"32" "" ( , , , , , )'表示内存分区的结构信息类型的变量类型'分区首地址'分区长度'分区状态-1表示不存在,0表示空闲分区,1表示已经分配的分区'该分区正在活动的进程代号'定义最多640个,总共640K内存数组(1 640)'表示可以使用的进程代号(1 640)'0表示该进程号可以使用'.>=1表示该进程号不可以使用'表示分配方法'0=最先分配'1=最优分配'2=最坏分配()'取可以使用的进程号ii = 1 640(i) = 0(i) = 1= i= 0()'取可以使用的为了表示分区的存储空间,模拟c语言的指针ii = 1 640(i) = -1= i= 0( )i,'分配新的分区0 '最先适应按地址找i = 1 640(i) = 0(i) >== ii1 '最优适应,找最小可以满足的= 10000i = 1 640(i) = 0(i) >=(i) <= (i)= ii= 0("内存不足!", )=2 '最坏适应,找最大可以满足的= 10000i = 1 640(i) = 0(i) >=(i) >= (i)= ii= 0("内存不足!", )=("内存不足!", ) ()ijL'新的进程进入= ()= ()i = ()(i) = 1L = (i) -(i) =(i) =L > 0= ()() = 0() = L() = (i) +()i = ((1) * 6 + 1)= (i):"请在文本框内输入正确的数字"()'刷新显示ij, ki = 1 640(i) <> -1(i) = 1(i 2) = 1= 4= 5= 6= (i)= (i)= (i)j = + 1(i) = 1(j, 1) = (i)(j, 2) = ((i)) + "K"(j, 3) = ((i)) + "K"(j, 4) = ((i)) + "已分配"(j, 5) = () + "号进程"(i) = 0(j, 1) = (i)(j, 2) = ((i)) + "K"(j, 3) = ((i)) + "K"(j, 4) = ((i)) + "未分配"(j, 5) = ""k = 1 5= kj = + 1 += j=j <> + 1(, ) = ""jk()ip, nj'回收进程的内存和合并空闲分区= ()i = 1 640(i) ='既无上邻又无下邻(i) = 0(i) = 0() = 0i = 1n = 0'找下一个相连的分区j = 1 640(i) + (i) = (j)(j) = 0n = jjn <> 0'有下邻(i) = (i) + (n)(n) = -1i = 640p = 0'找上一个相连的分区j = 1 640(j) + (j) = (i)(j) = 0p = jjp <> 0''有上邻(p) = (p) + (i)(i) = -1p = 0n = 0'找上一个相连的分区j = 1 640(j) + (j) = (i)(j) = 0p = jj'找下一个相连的分区j = 1 640(i) + (i) = (j)(j) = 0n = jjp <> 0 n <> 0'既有上邻又有下邻(p) = (p) + (i) + (n)(i) = -1(n) = -1p <> 0''只有上邻(p) = (p) + (i)(i) = -1n <> 0'只有下邻(i) = (i) + (n)(n) = -1("不存在这个进程!", ):("不存在这个进程!", )()i(1) = 1800(2) = 1800(3) = 1800(4) = 1800(5) = 1800(0, 0) = "内存地址" (0, 1) = "分区号"(0, 2) = "分区首址" (0, 3) = "分区长度" (0, 4) = "分配状态" (0, 5) = "活动进程"= 0= 0i = 0 639(i + 1, 0) = (i) + "K"i = 1 640(i) = -1(1) = 0(1) = 640(1) = 0(1) = 0= "存储管理器"( i )'延迟i秒t1, t2t1 = ()t2 = t1(t2 - t1 < i)t2 = ()()("")()("作者:顾熙杰" + + "考客主页:", 48) ()()( + "\")( )i'外浏览器访问网页i = (0&, , , , , )' i'返回10767正确'返回2,文件不存在i = 2("文件不存在", 48):$1()= 02()= 13()= 2( b )'寻找上邻区ii = b - 1 1 -1(i) <> -1= i( b )'寻找下邻区ii = b + 1 640(i) <> -1= i7)运行结果用户区分配前分配了5个进程一个进程退出以后。
可变分区存储管理的内存分配算法模拟实现----最佳适应算法 -回复
可变分区存储管理的内存分配算法模拟实现----最佳适应算法-回复可变分区存储管理是一种内存管理技术,其通过将内存分割成不同大小的区域来存储进程。
每个进程被分配到与其大小最匹配的区域中。
内存分配算法的选择影响了系统的性能和资源利用率。
本文将介绍最佳适应算法,并模拟实现该算法。
一、什么是最佳适应算法?最佳适应算法是一种可变分区存储管理中的内存分配策略。
它的基本思想是在每次内存分配时选择最合适的空闲区域。
具体来说,它从可用的空闲区域中选择大小与需要分配给进程的内存最接近的区域。
二、算法实现思路最佳适应算法实现的关键是如何快速找到最合适的空闲区域。
下面给出一个模拟实现的思路:1. 初始化内存分区列表,首先将整个内存定义为一个大的空闲区域。
2. 当一个进程请求分配内存时,从列表中找到与所需内存最接近的空闲区域。
3. 将该空闲区域分割成两部分,一部分分配给进程,并将该部分标记为已分配,另一部分留作新的空闲区域。
4. 更新内存分区列表。
5. 当一个进程释放内存时,将其所占用的内存区域标记为空闲,然后尝试合并相邻的空闲区域。
三、算法模拟实现下面是一个简单的Python代码实现最佳适应算法:pythonclass MemoryPartition:def __init__(self, start_addr, end_addr, is_allocated=False): self.start_addr = start_addrself.end_addr = end_addrself.is_allocated = is_allocatedclass MemoryManager:def __init__(self, total_memory):self.total_memory = total_memoryself.partition_list = [MemoryPartition(0, total_memory)]def allocate_memory(self, process_size):best_fit_partition = Nonesmallest_size = float('inf')# 找到最佳适应的空闲区域for partition in self.partition_list:if not partition.is_allocated and partition.end_addr - partition.start_addr >= process_size:if partition.end_addr - partition.start_addr < smallest_size:best_fit_partition = partitionsmallest_size = partition.end_addr - partition.start_addrif best_fit_partition:# 将空闲区域分割,并标记为已分配new_partition =MemoryPartition(best_fit_partition.start_addr,best_fit_partition.start_addr + process_size, True)best_fit_partition.start_addr += process_sizeself.partition_list.append(new_partition)return new_partition.start_addr,new_partition.end_addrelse:return -1, -1def deallocate_memory(self, start_addr, end_addr):for partition in self.partition_list:if partition.start_addr == end_addr and not partition.is_allocated:# 标记空闲区域partition.is_allocated = False# 尝试合并相邻空闲区域for next_partition in self.partition_list:if not next_partition.is_allocated andnext_partition.start_addr == end_addr:end_addr = next_partition.end_addrself.partition_list.remove(next_partition)breakelse:breakdef print_partitions(self):for partition in self.partition_list:if partition.is_allocated:print(f"Allocated Partition: {partition.start_addr} - {partition.end_addr}")else:print(f"Free Partition: {partition.start_addr} - {partition.end_addr}")# 测试最佳适应算法if __name__ == "__main__":mm = MemoryManager(1024)start, end = mm.allocate_memory(256)print(f"Allocated memory: {start} - {end}")mm.print_partitions()mm.deallocate_memory(start, end)print("Memory deallocated:")mm.print_partitions()以上代码实现了一个简单的内存管理器类`MemoryManager`,它具有`allocate_memory`和`deallocate_memory`等方法。
可变分区存储管理的内存分配算法模拟实现----最佳适应算法 -回复
可变分区存储管理的内存分配算法模拟实现----最佳适应算法-回复可变分区存储管理是一种常用的内存分配算法,用于管理计算机系统中的内存空间。
其中,最佳适应算法是其中一种经典的实现方式。
本文将围绕最佳适应算法展开,详细介绍其原理、实现方法以及优缺点。
首先,我们需要明确什么是可变分区存储管理。
在计算机系统中,内存是被划分为多个可用的分区,每个分区有不同的大小。
当一个程序需要内存时,系统会选择一个适合该程序大小的分区进行分配。
使用可变分区存储管理算法,系统可以灵活地分配和回收内存,并提高内存的利用率。
最佳适应算法是可变分区存储管理中的一种常用算法。
其核心思想是始终选择最小但足够容纳所需内存的分区进行分配。
这样可以最大程度地减少内存碎片的产生,提高系统内存利用率。
下面我们将一步一步来模拟实现最佳适应算法。
首先,我们需要创建一个数据结构来表示内存分区。
我们可以使用一个链表来存储每个分区的信息,每个节点包含分区的起始地址、结束地址和大小。
初始时,整个内存空间被视为一个大的可用分区。
接下来,当一个程序需要内存时,我们需要遍历整个分区链表,找到一个大小不小于所需内存的最小分区。
我们可以使用一个变量来记录当前找到的最小分区的大小,以及一个指针来指向该分区节点。
在遍历过程中,如果找到一个分区的大小恰好等于所需内存,那么直接分配给程序,并将该节点从链表中删除即可。
如果找到的分区的大小大于所需内存,我们需要进行分割操作。
即将该分区分成两个部分,一个部分分配给程序,另一个部分保留未分配状态,并将其添加到链表中。
同时,我们需要更新原有分区节点的起始地址和大小。
最后,当一个程序终止并释放内存时,我们需要将该内存块归还给系统,并进行合并操作。
即将释放的内存块与相邻的空闲内存块进行合并,以减少内存碎片。
通过以上步骤,我们可以实现最佳适应算法来管理内存分配。
但是,最佳适应算法也有其优缺点。
首先,最佳适应算法相对于其他算法来说,可以更好地减少内存碎片的产生。
3用C语言模拟实现可变式分区存储管理
试验三:用C语言模拟实现可变式分区存储管理一、試驗目标:1、通过编写可变式分区存储管理的C语言程序,使学生加强对可变式分区存储管理的认识。
2、掌握操作系统设计的根本原理、方法和一般步骤。
二、試驗容:用C語言編寫一個实现可变式的分区管理的模擬程序。
*复习相关的知识:1、分区管理的原理:将存储器划分成假设干段大小固定的区域,一个区域里只能运行一个程序,程序只能在其自身所在的分区中活动。
2、固定式分区管理的原理:区域大小及起始地址是固定的。
一个分区只能存放一个程序。
需要设置一个分区说明表来标明存的使用状态。
根据分区说明表来给程序分配相应的区域。
由于程序不可能刚刚占有一个分区的大小,这样就会在一个分区之中留下零头,造成了极大的浪费。
3、可变式分区管理的原理:区域的大小及起始地址是可变的,根据程序装入时的大小动态地分配一个区域。
保证每个区域之中刚好放一个程序。
这样可以充分地利用存储空间,提高存的使用效率。
如果一个程序运行完毕,就要释放出它所占有的分区,使之变成空闲区。
这样就会出现空闲区与占用区相互交织的情况。
这样就需要P表,F表来分别表示存的占用区状态与空闲区的状态。
*确定该系统所使用的数据构造:我们可以把存表示为一个数组的形式。
这个数组中的每一个单元都是一个无符号的字符型的数据类型。
这样一个单元刚好占用一个字节的大小。
这一个字节的地址可以用它在此数组中的下标来表示。
如果一个程序占用了一定的区域,则这个区域的大小就可以用它占有的字节数的个数来表示。
用C语言可以表述如下:unsigned char memory[1024]它就可以表示一个1K的存空间。
为了实现可变式的分区管理,还需要设立两个表,一个是P表,一个是F表,它们分别表示存的占用区状态。
由于在该程序运行的过程之中需要不断地修改P表和F表,所以这两个表不适合于用数组的形式来表示;而应该使用单链表的形式。
这样就要给单链表中的结点确立一个数据构造。
很显然,P表中的每一个结点至少要包括以下的几项:占用的程序名、占用区的起始地址、占用区的大小、指向下一个结点的指针。
实验、可变分区存储管理系统模拟——最先适应分配算法
实验、可变分区存储管理系统模拟——最先适应分配算法1. 实验⽬的可变分区分配是⼀种重要的存储管理思想,⽬前流⾏的操作系统采⽤的分段存储管理的基本思想就源⾃该⽅法。
本实验的⽬的是通过编程来模拟⼀个简单的可变分区分配存储管理系统,利⽤最先适应分配算法实现。
经过实验者亲⾃动⼿编写管理程序,可以进⼀步加深对可变分区分配存储管理⽅案设计思想的理解。
2. 实验原理固定分区分配按操作系统初始化时划定的分区⽅案为作业分配内存,由于各分区的位置和⼤⼩固定,因此作业所需的内存⼤⼩通常⼩于分到的实际内存的⼤⼩,造成存储空间的浪费。
可变分区分配对此作了改进,它总是根据作业的实际需要分配刚好够⽤的连续存储空间,保证分配给作业的存储空间都是有⽤的,避免了零头的产⽣。
(1)可变分区中的数据结构建⽴描述作业的数据结构作业控制块,⾄少应包括:作业名称作业需要执⾏时间作业的内存需求作业调⼊主存时间作业执⾏结束时间作业所在分区的起始地址建⽴描述内存已分配分区的数据结构;建⽴描述内存未分配的空闲分区的数据结构;空闲分区和已分配分区的信息可以使⽤分区表来描述。
系统中所有空闲分区构成分区表,所有已分配分区构成分配分区表。
出于效率的考虑,也可使⽤分区链来记录分区信息。
分区链是⼀种双向链表,链表的每个结点描述⼀个分区的信息。
系统中所有空闲分区构成空闲分区链,所有已分配分区构成分配分区链。
分配和回收分区时,需要在这两个链表中进⾏结点的查找和插⼊、删除与修改操作。
为改进算法的执⾏效率,可以将分区链按特定的顺序排序。
分区链结点的数据结构为:Struct Section {Section *pPre; //前向指针,指向链表的前⼀个结点int nSart; //分区的起始地址int nSize; //分区的尺⼨Section *pSuf; //后向指针,指向链表的后⼀个结点};可变分区分配算法——最先适应分配算法最先适应分配算法要求空闲分区按地址递增的顺序排列,在进⾏内存分配时,从低地址部分向⾼地址部分查找,直到找到⼀个能满⾜要求的空闲分区为⽌。
实验上机02-可变分区存储管理程序模拟的实现
实验题目可变分区存储管理的程序模拟一、可变分区存储管理的基本策略1)不预先划分几个固定分区,分区的建立是在作业的处理过程中进行的,各分区的大小由作业的空间需求量决定。
2)采用指针方式将各个空闲分区链接而成的链表,用以记录主存分配现状。
3)分配与回收算法按空闲分区链接方式的不同分类,有最佳、最坏、首次和下次适应四种算法。
二、程序模拟的设计1、基本思想采用事件驱动模型。
事件有:1)申请主存事件,表示一个作业创建时提出的主存资源要求;2)释放主存事件,表示一个作业结束时其占用主存被回收。
2、数据结构设计1)程序使用的常值和工作变量的说明作业表所含表项的最大数量 MaxAmountOfJobTableItems 10处理的作业的最大数量 MaxAmountOfJobs 20主存空间的最大尺寸 MaxSizeOfMemorySpace 1000作业申请主存的最大尺寸 MaxSizeOfMemoryForAsk 500时间单位的最大值 MaxSizeOfTimeUnit 100占用主存时间单位的最大值 MaxSizeOfOccupyTimeUnit 300占用标志 BUSY 1空闲标志 FREE 0申请标志 ASK 1释放标志 RELEASE 0逻辑是标志 TRUE 1逻辑否标志 FALSE 0尾标志 END -1当前时间 CurrentTime作业计数器 CounterOfJobs作业命名序列字符 SerialCharOfJobName2)事件与事件表typedef struct Event_DataType{ 事件数据类型的定义int EventType; 事件的类型申请ASK或释放RELEASEint OccurTime; 事件发生的时间char JobName; 申请主存或被回收主存的作业名int JobId; 进入系统的作业在作业表中相应表项的编号int SizeOfMemoryForAsk; 作业申请占用主存的尺寸int OccupyTimeOfMemoryForAsk; 作业申请占用主存的时间长度int WaitFlag; 该事件是否等待过TRUE或FALSEint AdmitTime; 申请事件的提交时间或释放事件的处理时间struct Event_DataType *Next; 下一事件的指示信息} Event_DataType;设立3个事件表事件表TableOfEvents等待事件表TableOfWaitEvents 用于存放未能及时处理的主存申请事件统计事件表TableOfSumEvents 用于备份事件表3)字单元与主存空间typedef struct Word_DataType{ 主存物理单元数据类型定义int State; 所在分区的状态 FREE或BUSYint Size; 所在分区的大小char JobName; 占用分区的作业名int Next; 相邻分区的指示信息(前相邻或后相邻)} Word_DataType;主存空间是字单元的数组MemorySpace[MaxSizeOfMemory]4)作业表项与作业表typedef struct JobTableItem_DataType{ 作业表项的数据类型定义int State; 表项的状态FREE或BUSYchar JobName; 占用的作业名int MemoryLocation; 作业的主存位置int OccupyTimeOfMemory; 作业占用主存的时间长度int Next; 下一个空闲表项} JobTableItem_DataType;作业表是作业表项的数组TableOfJobs[MaxAmountOfJobTableItems] 5)核心数据结构typedef struct KernalDataStructure_DataType{ 核心数据结构数据类型定义JobTableItem_DataType TableOfJobs[MaxAmountOfJobTableItems];一张作业表int AmountOfFreeItems; 空闲表项的数量int FirstFreeItem; 第一个空闲表项int AmountOfFreeAreas; 空闲分区的数量int FirstFreeArea; 第一个空闲分区int SizeOfFreeMemory; 空闲主存的尺寸} KernalDataStructure_DataType;3、处理流程设计参数说明:形、变参数的区分按参数的逻辑意义认定。
实验五 动态分区分配方式内存管理模拟
实验五动态分区分配方式内存管理模拟一、实验目的1)掌握连续分配方式内存管理理论2)掌握动态分区分配方式内存管理理论二、实验原理动态分区分配:根据进程的实际需要,动态地创建分区为之分配内存空间,在实现动态分区分配时,将涉及分区分配中所使用的数据结构,分区分配算法和分区的分配与回收操作等问题。
1)分区分配中的数据结构空闲分区表:一个数据表,用于记录每个空闲块的情况,如起始地址、大小、使用情况等;空闲分区链表:把所有的空闲分区链接成一个链表,便于内存空间查看与分配回收。
2)分配算法首次适应法:空闲分区按首地址递增次序组织,每次查找时从链首出发,寻找满足要求的内存块。
循环首次适应算法:空闲分区按首地址递增次序组织,每次从上次查找的下一个空闲块开始查找,直到找到满足要求的内存块。
最佳适应法:空闲分区按空闲分区大小址递增次序组织,每次查找时从链首出发,寻找满足要求的最小内存块进行分配。
最坏适应法:空闲分区按空闲分区大小递减次序组织,每次查找时直接判断最大空闲分区是否满足要求。
3)内存分配过程利用分配算法找到满足要求的内存块,设请求的内存大小为size:若找到的空闲分区的大小等于size,完全分配;若找到的空闲分区大小大于size,且一分为二后,剩余大小小于1K,则不再分割,作为整体进行分配;否则一分为二,剩余部分仍然作为空闲分区存在;若无满足要求空闲分区,则分配失败4)内存回收根据释放区首址和大小,查找空闲分区表/链表,判断是否有相邻的空闲分区存在:释放区与前空闲区相邻:将释放区与前空闲区合并为一个空闲区。
其首址仍为前空闲区首址,大小为释放区大小与空闲区大小之和。
释放区与前后两个空闲区相邻:将这三个区合为一个空闲区,其首址为前空闲区首址,大小为这三个区大小之和,并取消原后空闲区表目。
释放区与后空闲区相邻:则把释放区合并到后空闲,首地址为释放区首地址,大小为二者大小之和。
释放区不与任何空闲区相邻:将释放区作为一个空闲区,将其大小和首址插入到空闲区表的适当位置。
动态分区分配方式的模拟实验原理说明
动态分区分配方式的模拟实验原理说明一、引言动态分区分配方式是计算机内存管理中一种常见的分配方式,它将内存按需划分为多个独立的区域,用于分配进程所需的内存空间。
本文将详细探讨动态分区分配方式的原理及其在模拟实验中的应用。
二、动态分区分配方式的原理动态分区分配方式基于内存动态分配,将可用内存划分为多个不连续的分区,每个分区可用于存放一个进程或程序。
此分配方式具有灵活性,能够更好地满足不同程序对内存空间的需求。
2.1 空闲内存分区列表在动态分区分配方式中,操作系统维护一个空闲内存分区列表,记录可供分配的内存空间情况。
列表中的每个分区都有其起始地址和长度。
2.2 分区分配算法动态分区分配方式有多种分区分配算法可供选择,主要包括首次适应算法、最佳适应算法和最差适应算法。
•首次适应算法:从空闲分区列表中找到第一个满足分配要求的分区进行分配。
•最佳适应算法:从空闲分区列表中找到最小的满足分配要求的分区进行分配。
•最差适应算法:从空闲分区列表中找到最大的满足分配要求的分区进行分配。
2.3 分区回收算法当进程结束或释放内存时,操作系统需要将其占用的内存空间回收,归还给空闲内存区。
分区回收算法的目标是尽可能地合并相邻的空闲区域,以最大程度地提供可用内存。
三、动态分区分配方式的模拟实验为了更好地理解和研究动态分区分配方式,可以进行一系列模拟实验。
下面将介绍动态分区分配方式的模拟实验原理及步骤。
3.1 实验原理动态分区分配方式的模拟实验基于以下原理: - 创建一个内存模拟环境,模拟操作系统管理的内存空间。
- 设计一系列测试用例,模拟进程的创建、分配和回收过程。
- 根据所选的分区分配算法和分区回收算法,计算分区分配和回收的效果。
- 比较不同算法在性能方面的差异,并分析其优缺点。
3.2 实验步骤动态分区分配方式的模拟实验包括以下步骤: 1. 初始化内存模拟环境,创建一个空闲分区列表。
2. 设计多个测试用例,包括不同大小和数量的进程。
动态分区式存储管理
可变分区存储管理设计思路:整体思路:可变分区管理方式将内存除操作系统占用区域外的空间看做一个大的空闲区。
当作业要求装入内存时,根据作业需要内存空间的大小查询内存中的各个空闲区,当从内存空间中找到一个大于或等于该作业大小的内存空闲区时,选择其中一个空闲区,按作业需求量划出一个分区装人该作业,作业执行完后,其所占的内存分区被收回,成为一个空闲区。
如果该空闲区的相邻分区也是空闲区,则需要将相邻空闲区合并成一个空闲区。
设计所才用的算法:采用最优适应算法,每次为作业分配内存时,总是把既能满足要求、又是最小的空闲分区分配给作业。
但最优适应算法容易出现找到的一个分区可能只比作业所需求的长度略大一点的情行,这时,空闲区分割后剩下的空闲区就很小以致很难再使用,降低了内存的使用率。
为解决此问题,设定一个限值minsize,如果空闲区的大小减去作业需求长度得到的值小于等于minsize,不再将空闲区分成己分分区和空闲区两部分,而是将整个空闲区都分配给作业。
内存分配与回收所使用的结构体:为便于对内存的分配和回收,建立两张表记录内存的使用情况。
一张为记录作业占用分区的“内存分配表”,内容包括分区起始地址、长度、作业名/标志(为0时作为标志位表示空栏目);一张为记录空闲区的“空闲分区表”,内容包括分区起始地址、长度、标志(0表空栏目,1表未分配)。
两张表都采用顺序表形式。
关于分配留下的内存小碎片问题:当要装入一个作业时,从“空闲分区表”中查找标志为“1”(未分配)且满足作业所需内存大小的最小空闲区,若空闲区的大小与作业所需大小的差值小于或等于minsize,把该分区全部分配给作业,并把该空闲区的标志改为“0”(空栏目)。
同时,在已分配区表中找到一个标志为“0”的栏目登记新装人作业所占用分区的起始地址,长度和作业名。
若空闲区的大小与作业所需大小的差值大于minsize。
则把空闲区分成两部分,一部分用来装入作业,另外一部分仍为空闲区。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
青岛农业大学理学与信息科学学院操作系统课程设计报告设计题目仿真实现动态可变分区存储管理模拟系统—最佳适应算法和最先适应算法学生专业班级计算机科学与技术2011级03班学生姓名(学号)明珠(H20110684 )设计小组其他同学姓名(学号)玉婷(H20110661)宋璇(H20110162)指导教师牟春莲完成时间2014. 06.15实习(设计)地点信息楼2182014年6月16日一、课程设计目的操作系统的理论知识只有通过操作系统的实际操作和编程才能真正地理解和掌握,没有实践操作系统的操作和编程,学习操作系统就是纸上谈兵。
操作系统课程设计是在学习完《操作系统》课程后进行的一次全面、综合实习,是计算机科学与技术专业的重要实践性教学环节。
通过课程设计,达到如下目的:1、巩固和加深对操作系统原理的理解,提高综合运用本课程所学知识的能力。
2、培养学生选用参考书,查阅手册及文献资料的能力;培养独立思考、深入研究、分析问题、解决问题的能力。
3、通过实际操作系统的分析设计、编程调试,掌握系统软件的分析方法和工程设计方法。
4、能够按要求编写课程设计报告书,能正确阐述设计过程和实验结果、正确绘制系统和程序框图。
5、通过课程设计,培养学生严谨的科学态度、严肃认真的工作作风和团队协作精神。
二、设计任务题目描述:仿真实现动态可变分区存储管理模拟系统。
存调度策略可采用最先适应算法、最佳适应法等,并对各种算法进行性能比较。
为了实现分区分配,系统中必须配置相应的数据结构,用来描述空闲区和已分配区的情况,为分配提供依据。
常用的数据结构有两种形式:空闲分区表和空闲分区链。
为把一个新作业装入存,须按照一定的算法,从空闲分区表或空闲分区链中选出一个分区分配给该作业. 设计要求:1.采用指定算法模拟动态分区管理方式的主存分配。
能够处理以下的情形:⑴随机出现的进程i申请jKB存,程序能判断是否能分配,如果能分配,要求输出分配的首地址Faddress,并要求输出存使用情况和空闲情况。
存情况输出的格式为:Faddress该分区的首地址;Eaddress该分区的尾地址Len 分区长度;Process 如果使用,使用的进程号,否则为0。
⑵主存分配函数实现寻找空闲区、空闲区表的修改、已分配区表的修改功能。
成员分工:明珠申请存、查看进程之间的前后的区域状态、释放进程玉婷最先适应算法、将其释放的存插入空闲块中、初始化宋璇最佳适应算法、将新项插入已分配表中、退出明珠宋璇玉婷整个界面的优化、界面设计、总体思路三、分析与设计1.设计思路存储器是计算机的重要组成部分,存储空间是操作系统管理的宝贵资源,虽然其容量在不断扩大,但仍然远远不能满足软件发展的需要。
对存储资源进行有效的管理,不仅关系到存储器的利用率,而且还对操作系统的性能和效率有很大的影响。
操作系统的存储管理的基本功能有:存储分配、地址转换和存储保护、存储共享、存储扩充。
存储分配指为选中的多道运行的作业分配主存空间;地址转换是把逻辑地址空间中的用户程序通过静态重定位或动态重定位转换和映射到分给的物理地址空间中,以便用户程序的执行;存储保护指各道程序只能访问自己的存储区域,而不能互相干扰,以免其他程序受到有意或无意的破坏;存储共享指主存中的某些程序和数据可供不同用户进程共享。
最简单的单道系统中,一旦一个程序能装入主存,它将一直运行直到结束。
如果程序长度超出了主存的实际容量,可以通过覆盖和交换的技术获得解决。
更多的操作系统支持多个用户进程在主存同时执行,能满足多道程序设计需要的最简单的存储管理技术是分区方式,有分固定分区和可变分区。
可变分区的分配(如图(1)所示)算法包括:最先适应、下次适应、最佳适应、最坏适应和快速适应等分配算法。
图(1)动态存分配采用分区方式管理存储器,每道程序总是要求占用主存的一个或几个连续的存储区域,主存中会产生许多碎片。
因此,有时为了接纳一个新的作业而往往要移动已在主存的信息,这不仅不方便,而且开销不小。
现代计算机都有某种虚存硬设备支持,简单也是常用的虚存是请求分页式虚存管理,于是允许把一个进程的页面存放到若干不相邻的主存页框中。
从搜索速度上看,最先适应算法具有最佳性能。
从回收过程来看,最先适应法也是最佳的。
最先适应算法要求可用表或自由按起始地址递增的次序排列。
该算法的最大特点是一旦找到大于或等于所要求存的长度的分区,则搜索结束。
其优点:(1)、在释放存分区时,如果有相邻的空白区就进行合并,使其成为一个较大的空白区;(2)、本算法的实质是尽可能的利用存储器的低地址部分,在高地址部分则保留较多的或较大的空白区,以后如果需要较大的空白区,就容易能够满足。
最佳适应算法:从全部空闲区中找出能满足作业要求的、且大小最小的空闲分区,这种方法能使碎片尽量小。
为适应此算法,空闲分区表(空闲区链)中的空闲分区要按从小到大进行排序,自表头开始查找到第一个满足要求的自由分区分配。
该算法保留大的空闲区,但造成许多小的空闲区。
最佳适应算法将可利用空间表中一个大小不小于“请求”且最接近“请求”的空闲块的一部分分配给用户。
分配与回收都需要对可利用空间表从头至尾查询一遍。
为了避免每次分配都要查询整个链表,通常要求节点从大到小排序,由此只需找到第一个足够大的空闲块即可予以分配。
但回收时,必须把回收的空闲块放置在符合大小顺序关系的链表位置。
在分配时容易产生太小而无法利用的存碎片,同时这种做法也保留了那些很大的存块以备响应将来发生的存量较大的用户“请求”,从而使整个链表逐渐趋向于节点大小差别甚远的状态。
这种分配算法适合请求分配存大小围较广的系统,此算法比较费时间。
在进行存分配时,从空闲分区表(或空闲分区链)首开始顺序查找,直到找到第一个能满足其大小要求的空闲分区为止。
如果该空闲分区大于作业的大小,则从该分区中划出一块存空间分配给请求者,将剩余空闲区仍然留在空闲分区表(或空闲分区链)中。
最佳适应算法的特点:按最佳适应算法为作业分配存,就能把既满足作业要求又与作业大小最接近的空闲分区分配给作业。
保留了大的空闲区,但分割后的剩余空闲区很小。
本课程设计就是分析动态分区法,与固定分区法相比,动态分区法在作业执行前并不建立分区,分区的建立是在作业的处理过程中进行的。
且其大小可随作业或进程对存的要求而改变分区的建立是在作业的处理过程中进行的。
且其大小可随作业或进程对存的要求而改变。
这就改变了固定分区法中那种即使是小作业也要占据大分区的浪费现象,从而提高了存的利用率。
2.概要设计动态分区分配是根据进程的实际需要,动态地为之分配存空间。
在实现可变分区分配时,将涉及到分区分配中所用的数据结构、分区分配算法和分区的分配和回收操作这样三个问题。
为了实现分区分配,系统中必须配置相应的数据结构,用来描述空闲区和已分配区的情况,为分配提供依据。
常用的数据结构有两种形式:空闲分区表和空闲分区链。
为把一个新作业装入存,须按照一定的算法,从空闲分区表或空闲分区链中选出一个分区分配给该作业。
目前常用的分配算法有:首次适应算法、循环首次适应算法、最佳适应算法、最坏适应算法和快速适应算法。
在动态分区存储管理方式中,主要操作是分配存和回收.系统模块划分:图(2)各模块划分图主流程图:图(3)主流程图各程序模块的调用层次:图(4)各程序调用图 3.详细设计、 数据结构 结构体定义进程 struct area { int start; int end;int len; int sign;struct area * next;};5个数据成员,分别为:start(分区的首地址)、end、(分区尾地址)len (分区的长度)、sign(标志进程状态)、next(指针用来指向下一个进程)。
存分配表的图类似与图(5)所示:图(5)存分配图最先适应算法流程如下图所示请求SIZE大小的分区:否图(6)最先适应算法流程图最佳适应算法流程如下图所示:图(7)最佳适应算法流程图四、系统实施在模拟过程中,没有充分理解操作系统教程上关于动态分区法、最先适应法、最优适应法的概念,造成了对设计的目的设计不清楚,不能很好地表达出此设计的功能寻找空白区方法的不同:分区分配是对可用表(或自由链)数据结构进行操作,空闲区表可以按空闲区大小的升序(降序)和空闲区首址升序(降序)两种方法进行组织。
才开始并没有理解这两种分配方式对这最佳适应算法和最先适应算法的影响,导致混淆,出现了错误。
对题目理解有误,对模块之间的关系设计不是很清晰。
图(8)初始化图图(9) 申请存图图(10)查看已分配区图图(11)查看空闲区图图(12)释放存图图(13)查看存状态图最佳算法和最先算法的比较:图(13)两算法的对比图五、程序清单#include<iostream>using namespace std;#include<fstream>struct area {int start; 定义分区的首地址int end; 定义分区的尾地址int len; 定义分区的长度int sign;定义分区的进程号struct area * next;定义进程的指针};struct area*freehead=NULL;声明freehead 是型结构指针。
初始freehead指针为空。
struct area*usedhead=NULL;声明usedhead 是型结构指针。
初始usedhead指针为空。
void create();创建存区void print(area*);void ask(area*);void ask1(area*);void correct(area*,int);area * delempty();初始化void inserused(area *,int ,int );void inserfree(area * );void setfree();void listID();//最先适应法void listlen();/最优适应法void swap(area *,area *);//初始化area * delempty(){area * p1=freehead;把空闲区首地址赋值给p1if(p1->len==0){if(p1->next==NULL)return NULL;else {p1=p1->next;指向下一个地址}}}//最优适应法void listlen(){int n=0; 初始为零area *p9=freehead->next,*p0=freehead,*p11,*p12,*p13;while(p0!=NULL){不为空p0=p0->next;指向下一个地址n++;n加一}p0=freehead;把空闲区赋值给p0if (n==1)return;elsewhile(p9!=NULL) {p12=p0; 把p0空闲区给p12p13=p9;把p9空闲区给p13p0=p0->next; p0指向下一个地址p9=p9->next;while(p13!=NULL)//把空闲区按从小到大的顺序排列{if((p12->len)>(p13->len)){如果p12长度>p13长度p11=new area;//把p13给p11p11->end=p13->end;p11->len=p13->len;p11->sign=p13->sign;p11->start=p13->start;p11->next=NULL;swap(p13,p12);交换两个P13,P12swap(p12,p11);交换两个P12,P11}p13=p13->next;}}}void swap(area *p13,area *p14){p13->len=p14->len;p13->sign=p14->sign;p13->end=p14->end;p13->start=p14->start;}//最先适应法void listID(){int n=0;area *p9=freehead->next,*p0=freehead,*p11,*p12,*p13;while(p0!=NULL){p0=p0->next;n++;}p0=freehead;if (n==1)return;elsewhile(p9!=NULL) {p12=p0;p13=p9;p0=p0->next;p9=p9->next;while(p13!=NULL)//把地址按递增顺序排列{if((p12->start)>(p13->start)){p11=new area;p11->end=p13->end;p11->len=p13->len;p11->sign=p13->sign;p11->start=p13->start;p11->next=NULL;swap(p13,p12);swap(p12,p11);}p13=p13->next;}}}void inserfree(area * p3){查看进程之间的前后的区域状态int flag=0;area *pf=freehead,*pe=freehead,*pe1;while(pf!=NULL){if(pf->end!=p3->start)//判断是否有前继空闲块pf=pf->next;else break;}if(pf!=NULL){flag=5;}//flag=5 有前置空闲块else flag=1;//没有置1while(pe!=NULL)//判断是否有后继空闲块{if(pe->start!=p3->end){pe1=pe;pe=pe->next;}else break;}if(pe!=NULL) {if(flag==5)flag=6;else flag=4;}//有前置且有后置FLAG=6,只有后置=4else{if(flag==1)flag=2;}//前后都没有置2switch(flag){case 5:pf->end=pf->end+p3->len;前置空闲块pf->len=pf->len+p3->len;break;case 4:pe->start=pe->start-p3->len;只有后置pe->len=pe->len+p3->len;break;case 2: area* p8;p8=new area;p8->start=p3->start;p8->len=p3->len;p8->sign=0;p8->end=p3->end;p8->next=freehead;freehead=p8;break;case 6:pf->end=pe->end;有前置与后置pf->len=pf->len+pe->len+p3->len;if(pe->next==NULL){pe1->next=NULL;delete pe;}else {if(pe==freehead){freehead=pe->next;delete pe;}else {pe1->next=pe->next;delete pe;}}break;default :break;}}void setfree(){ 释放进程int chose;cout<<"选择一个要释放的任务:";cin>>chose;area*p7=usedhead,*p2;while( p7!=NULL) { //寻找有无此进程if( p7->sign!=chose ){p2=p7;p7=p7->next;}else break;}if(p7==NULL){cout<<"没有此进程,释放存失败,返回修改!"<<endl;return;}inserfree(p7);//将其释放的存插入空闲块中if(p7==usedhead &&p7->next==NULL)usedhead=NULL;else{if(p7->next==NULL){p2->next=NULL;delete p7;}//将次进程从已分配表中删除else {if(p7==usedhead){usedhead=p7->next;delete p7;}else {p2->next=p7->next;delete p7;}}}cout<<"成功释放所选任务的存!当前存状况为:"<<endl;print(freehead);print(usedhead);cout<<endl;}void inserused(area *p3,int num,int need){//将新项插入已分配表中area*p5;if(usedhead==NULL){p5=new area;p5->start=p3->start;p5->len=need;p5->sign=num;p5->end=p3->start+need;p5->next=NULL;usedhead=p5; }else{p5=new area;p5->start=p3->start;p5->len=need;p5->sign=num;p5->end=p3->start+need;p5->next=usedhead;usedhead=p5;}}void correct(area*p3,int need1){修改列表p3->len=p3->len-need1;p3->start=p3->start+need1;}void create(){ 创建地址长度area* p1;p1=new area;p1->start=0;p1->end=999;p1->len=999;p1->sign=0;p1->next=NULL;freehead= p1;}void ask1(area*freehead){//读文件初始化,只用一次int num,need;area*p3=freehead;ifstream infile("123.TXT");while(infile>>num){infile>>need;if(p3->len<need){cout<<"存不足,分配失败!"<<endl;return;}elseinserused(p3,num,need);correct(p3,need);}}void ask(area*freehead){申请存int num,need;area*p3=freehead,*p31=freehead;cout<<"input num and need! "<<endl;cin>>num;cin>>need;while( p3!=NULL){if(p3->len<need){p31=p3;p3=p3->next;}else break;}if(p3==NULL){cout<<"存不足,分配失败!"<<endl;return;}inserused(p3,num,need);correct(p3,need);freehead=delempty();cout<<"成功分配申请,当前存状况为:"<<endl;print(freehead);print(usedhead);cout<<endl;}void print(area*pp){显示页面area*p;p=pp;cout<<"────────────────────────────\n";if(p==NULL){cout<<"empty list!"<<endl;cout<<"────────────────────────────\n";return;}elsedo{cout<<"start:"<<p->start<<" end:"<<p->end<<" len:"<<p->len<<" sign:"<<p->sign<<endl;p=p->next;}while(p!=NULL);cout<<"────────────────────────────\n";}int main(){ int yourchose,flag1=0,flag2=0;int what;cout<<">>>>现在初始化存>>>>>>>\n";cout<<"请选择:1.手动初始化 2.读取文件初始化:";cin>>flag2;create();if(flag2==2)ask1(freehead);cout<<"存初始状态为:\n";print(freehead);print(usedhead);cout<<endl;cout<<"-------------菜单选项------------------\n";cout<<"1.申请存 2.释放作业的存\n";cout<<"3.查看空闲块链 4.查看已分配块链\n";cout<<"5.查看存状态0.退出\n";cout<<"---------------------------------------"<<endl;; while(flag1==0){ cout<<"-----请选择操作---- :";cin>>yourchose;switch(yourchose){ case 1: cout<<"选择哪种方式?1.最先适应2.最优适应: ";cin>>what;if(what==1)listID();else listlen();ask(freehead);break;case 2:setfree();.释放作业的存break;case 3:print(freehead);查看空闲块链break;case 4:print(usedhead);查看已分配块链\break;case 5: print(freehead);查看存状态print(usedhead);break;case 0:flag1=1;退出break;default: break;}}return 0;}六、总结与体会在一开始老师布置这次的实验题目时,自己根本不知道要干什么,因为在上课时对动态分区分配这节容不是太了解,所以在上机时不知道如何下手,后来,将本章容反复的看了几遍之后,终于有了自己的思路。