动态可变分区存储管理模拟系统
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,采用搬家算法第七组数据大家自行设计,不采用搬家算法,但不能全部分配第八组数据与第七组数据相同,但采用搬家算法后可以全部分配。
- 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;}六、总结与体会在一开始老师布置这次的实验题目时,自己根本不知道要干什么,因为在上课时对动态分区分配这节容不是太了解,所以在上机时不知道如何下手,后来,将本章容反复的看了几遍之后,终于有了自己的思路。