计算机操作系统内存分配实验报告
操作系统实验实验报告 虚拟内存

操作系统实验实验报告虚拟内存一、实验目的本次操作系统实验的目的是深入理解虚拟内存的概念、原理和实现机制,通过实际操作和观察,掌握虚拟内存的相关技术,包括页面置换算法、内存分配策略等,并分析其对系统性能的影响。
二、实验环境操作系统:Windows 10 专业版开发工具:Visual Studio 2019编程语言:C++三、实验原理1、虚拟内存的概念虚拟内存是一种计算机系统内存管理技术,它使得应用程序认为自己拥有连续的可用内存(一个连续完整的地址空间),而实际上,这些内存可能是被分散存储在物理内存和外部存储设备(如硬盘)中的。
虚拟内存通过将程序使用的内存地址映射到物理内存地址,实现了内存的按需分配和管理。
2、页面置换算法当物理内存不足时,操作系统需要选择一些页面(内存中的固定大小的块)换出到外部存储设备,以腾出空间给新的页面。
常见的页面置换算法有先进先出(FIFO)算法、最近最少使用(LRU)算法、时钟(Clock)算法等。
3、内存分配策略操作系统在分配内存时,需要考虑如何有效地利用有限的物理内存资源。
常见的内存分配策略有连续分配、分页分配和分段分配等。
四、实验内容与步骤1、实现简单的虚拟内存系统使用 C++编写一个简单的虚拟内存模拟程序,包括内存页面的管理、地址映射、页面置换等功能。
2、测试不同的页面置换算法在虚拟内存系统中,分别实现 FIFO、LRU 和 Clock 算法,并对相同的访问序列进行测试,比较它们的页面置换次数和缺页率。
3、分析内存分配策略的影响分别采用连续分配、分页分配和分段分配策略,对不同大小和类型的程序进行内存分配,观察系统的性能(如内存利用率、执行时间等)。
具体步骤如下:(1)定义内存页面的结构,包括页面号、标志位(是否在内存中、是否被修改等)等。
(2)实现地址映射函数,将虚拟地址转换为物理地址。
(3)编写页面置换算法的函数,根据不同的算法选择要置换的页面。
(4)创建测试用例,生成随机的访问序列,对不同的算法和分配策略进行测试。
操作系统实验报告6

操作系统实验报告6一、实验目的本次操作系统实验的主要目的是深入了解和掌握操作系统中进程管理、内存管理、文件系统等核心概念和相关技术,通过实际操作和观察,增强对操作系统工作原理的理解,并提高解决实际问题的能力。
二、实验环境本次实验使用的操作系统为 Windows 10,实验工具包括 Visual Studio 2019 等。
三、实验内容(一)进程管理实验1、创建多个进程,并观察它们的运行状态和资源占用情况。
通过编写简单的C++程序,使用Windows API 函数创建多个进程。
在程序中,设置不同的进程优先级和执行时间,观察操作系统如何调度这些进程,以及它们对 CPU 使用率和内存的影响。
2、进程间通信实现了进程间的管道通信和消息传递。
通过创建管道,让两个进程能够相互交换数据。
同时,还使用了 Windows 的消息机制,使进程之间能够发送和接收特定的消息。
(二)内存管理实验1、内存分配与释放使用 C++的动态内存分配函数(如`malloc` 和`free`),在程序运行时动态申请和释放内存。
观察内存使用情况,了解内存碎片的产生和处理。
2、虚拟内存管理研究了 Windows 操作系统的虚拟内存机制,通过查看系统的性能监视器,观察虚拟内存的使用情况,包括页面文件的大小和读写次数。
(三)文件系统实验1、文件操作进行了文件的创建、读取、写入、删除等基本操作。
通过编写程序,对不同类型的文件(如文本文件、二进制文件)进行处理,了解文件系统的工作原理。
2、目录操作实现了目录的创建、删除、遍历等功能。
了解了目录结构在文件系统中的组织方式和管理方法。
四、实验步骤(一)进程管理实验步骤1、打开 Visual Studio 2019,创建一个新的 C++控制台项目。
2、在项目中编写代码,使用`CreateProcess` 函数创建多个进程,并设置它们的优先级和执行时间。
3、编译并运行程序,通过任务管理器观察进程的运行状态和资源占用情况。
计算机操作系统实验报告

计算机操作系统实验报告一、实验目的本次计算机操作系统实验的主要目的是深入了解操作系统的工作原理和功能,通过实际操作和观察,增强对操作系统概念的理解,提高解决实际问题的能力。
二、实验环境1、操作系统:Windows 10 专业版2、开发工具:Visual Studio 20193、编程语言:C++三、实验内容1、进程管理实验创建多个进程,并观察它们的执行顺序和资源占用情况。
使用进程控制块(PCB)来跟踪进程的状态变化,如就绪、运行、阻塞等。
2、内存管理实验模拟内存分配和回收算法,如首次适应算法、最佳适应算法和最坏适应算法。
观察不同算法在内存利用率和分配效率方面的表现。
3、文件系统实验创建、读取、写入和删除文件,了解文件的操作流程。
研究文件的存储结构和目录管理方式。
4、线程同步与互斥实验使用互斥锁和信号量来实现线程之间的同步和互斥操作。
观察在多线程环境下资源竞争和同步的效果。
四、实验步骤1、进程管理实验步骤编写 C++程序,使用系统调用创建多个进程。
在每个进程中输出进程的标识符和当前执行时间。
通过观察控制台输出,分析进程的执行顺序和资源占用情况。
2、内存管理实验步骤实现不同的内存分配算法,并在程序中模拟内存请求和释放的过程。
记录每次内存分配和回收的结果,计算内存利用率和分配时间。
3、文件系统实验步骤使用文件操作函数创建文件,并写入一些数据。
读取文件中的数据,并将其输出到控制台。
删除文件,观察文件系统的变化。
4、线程同步与互斥实验步骤创建多个线程,共享一些公共资源。
在访问公共资源的代码段前使用互斥锁或信号量进行同步控制。
观察线程的执行结果,确保资源的正确访问和修改。
五、实验结果与分析1、进程管理实验结果与分析实验结果显示,进程的执行顺序是不确定的,取决于操作系统的调度策略和进程的优先级。
资源占用情况也因进程的不同而有所差异,一些进程可能占用较多的 CPU 时间和内存,而另一些则相对较少。
2、内存管理实验结果与分析首次适应算法在分配速度上较快,但容易产生内存碎片。
实现内存分配实验报告(3篇)

第1篇一、实验目的1. 理解操作系统内存分配的基本原理和常用算法。
2. 掌握动态分区分配方式中的数据结构和分配算法。
3. 通过编写程序,实现内存分配和回收功能。
二、实验环境1. 操作系统:Linux2. 编程语言:C语言3. 开发工具:GCC编译器三、实验原理1. 内存分配的基本原理操作系统内存分配是指操作系统根据程序运行需要,将物理内存分配给程序使用的过程。
内存分配算法主要包括以下几种:(1)首次适应算法(First Fit):从内存空间首部开始查找,找到第一个满足条件的空闲区域进行分配。
(2)最佳适应算法(Best Fit):在所有满足条件的空闲区域中,选择最小的空闲区域进行分配。
(3)最坏适应算法(Worst Fit):在所有满足条件的空闲区域中,选择最大的空闲区域进行分配。
2. 动态分区分配方式动态分区分配方式是指操作系统在程序运行过程中,根据需要动态地分配和回收内存空间。
动态分区分配方式包括以下几种:(1)固定分区分配:将内存划分为若干个固定大小的分区,程序运行时按需分配分区。
(2)可变分区分配:根据程序大小动态分配分区,分区大小可变。
(3)分页分配:将内存划分为若干个固定大小的页,程序运行时按需分配页。
四、实验内容1. 实现首次适应算法(1)创建空闲分区链表,记录空闲分区信息,包括分区起始地址、分区大小等。
(2)编写分配函数,实现首次适应算法,根据程序大小查找空闲分区,分配内存。
(3)编写回收函数,回收程序所占用的内存空间,更新空闲分区链表。
2. 实现最佳适应算法(1)创建空闲分区链表,记录空闲分区信息。
(2)编写分配函数,实现最佳适应算法,根据程序大小查找最佳空闲分区,分配内存。
(3)编写回收函数,回收程序所占用的内存空间,更新空闲分区链表。
3. 实验结果分析(1)通过实验,验证首次适应算法和最佳适应算法的正确性。
(2)对比两种算法在内存分配效率、外部碎片等方面的差异。
五、实验步骤1. 创建一个动态内存分配模拟程序,包括空闲分区链表、分配函数和回收函数。
内存管理实验报告

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

操作系统存储管理实验报告一、实验目的本次实验的目的是通过编写一段程序,实现对内存的分配和回收操作,并验证算法的正确性和性能。
二、实验内容1.实现首次适应算法首次适应算法是一种动态分配的内存管理算法,通过从低地址往高地址内存块,找到第一个满足需求的空闲块进行分配。
具体实现过程如下:(1)初始化内存空间,设置内存块的大小和地址范围;(2)编写一个函数,实现内存的分配操作,根据需求大小找到第一个合适的空闲块,并在其前后设置相应的标志位;(3)编写一个函数,实现内存的回收操作,根据释放块的地址,将其前后的标志位进行合并;(4)模拟应用程序的运行,测试内存的分配和回收操作。
2.实现最佳适应算法最佳适应算法是一种动态分配的内存管理算法,通过整个内存空间,找到最小的满足需求的空闲块进行分配。
具体实现过程如下:(1)初始化内存空间,设置内存块的大小和地址范围;(2)编写一个函数,实现内存的分配操作,遍历整个内存空间,找到满足需求且大小最小的空闲块进行分配;(3)编写一个函数,实现内存的回收操作,根据释放块的地址,将其前后的标志位进行合并;(4)模拟应用程序的运行,测试内存的分配和回收操作。
三、实验结果1.首次适应算法经过测试,首次适应算法能够正确地进行内存的分配和回收操作,并且算法的性能良好。
尽管首次适应算法在分配过程中可能会产生碎片,但是由于它从低地址开始,可以在较短的时间内找到满足需求的空闲块。
在实际应用中,首次适应算法被广泛采用。
2.最佳适应算法经过测试,最佳适应算法能够正确地进行内存的分配和回收操作,并且算法的性能较好。
最佳适应算法会整个内存空间,找到大小最小的满足需求的空闲块。
因此,在分配过程中不会产生很多的碎片,但是算法的执行时间较长。
四、实验总结通过本次实验,我们成功地实现了首次适应算法和最佳适应算法,并对算法的正确性和性能进行了验证。
两种算法在内存的分配和回收过程中都表现出良好的性能,可广泛应用于实际场景中。
操作系统-动态分区分配算法实验报告

实验题目:存储器内存分配设计思路:1.既然是要对内存进行操作,首先对和内存相关的内容进行设置我使用的是用自定义的数据结构struct来存放内存中一个内存块的内容包括:始地址、大小、状态(f:空闲u:使用e:结束)之后采用数组来存放自定义的数据类型,这样前期的准备工作就完成了2.有了要加工的数据,接下来定义并实现了存放自定义数据类型的数组的初始化函数和显示函数,需要显示的是每个内存块的块号、始地址、大小、状态3.接着依此定义三种动态分区分配算法首次适应算法、最佳适应算法和最差适应算法4.对定义的三种算法逐一进行实现①首次适应算法:通过遍历存放自定义数据类型的数组,找到遍历过程中第一个满足分配大小的内存块块号i,找到之后停止对数组的遍历,将i之后的块号逐个向后移动一个,然后将满足分配大小的内存块i分为两块,分别是第i块和第i+1块,将两块的始地址、大小、状态分别更新,这样便实现了首次适应算法②最佳适应算法:和首次适应算法一样,首先遍历存放自定义数据类型的数组,找到满足分配大小的内存块后,对内存块的大小进行缓存,因为最佳适应是要找到最接近要分配内存块大小的块,所以需要遍历整个数组,进而找到满足分配大小要求的而且碎片最小的块i,之后的操作和首次遍历算法相同③最差适应算法:和最佳适应算法一样,区别在于,最佳适应是找到最接近要分配内存块大小的块,而最差适应是要找到在数组中,内存最大的块i,找到之后的操作和最佳适应算法相同,因此不在这里赘述。
5.定义并实现释放内存的函数通过块号找到要释放的内存块,把要释放的内存块状态设置成为空闲,查看要释放的块的左右两侧块的状态是否为空闲,如果有空闲,则将空闲的块和要释放的块进行合并(通过改变块的始地址、大小、状态的方式)6.定义主函数,用switch来区分用户需要的操作,分别是:①首次适应②最佳适应③最差适应④释放内存⑤显示内存⑥退出系统实验源程序加注释:#include<bits/stdc++.h>#define MI_SIZE 100 //内存大小100typedef struct MemoryInfomation//一个内存块{int start; //始地址int Size; //大小char status; //状态 f:空闲 u:使用 e:结束} MI;MI MList[MI_SIZE];void InitMList() //初始化{int i;MI temp = { 0,0,'e' };for (i = 0; i < MI_SIZE; i++){MList[i] = temp;}MList[0].start = 0; //起始为0MList[0].Size = MI_SIZE;//大小起始最大MList[0].status = 'f'; //状态起始空闲}void Display() //显示{int i, used = 0;printf("\n---------------------------------------------------\n");printf("%5s%15s%15s%15s", "块号", "始地址", "大小", "状态");printf("\n---------------------------------------------------\n");for (i = 0; i < MI_SIZE && MList[i].status != 'e'; i++){if (MList[i].status == 'u'){used += MList[i].Size;}printf("%5d%15d%15d%15s\n", i, MList[i].start, MList[i].Size, MList[i].status == 'u' ? "使用" : "空闲");}printf("\n----------------------------------------------\n");}void FirstFit(){int i, j, flag = 0;int request;printf("最先适应算法:请问你要分配多大的内存\n");scanf("%d", &request);for (i = 0; i < MI_SIZE && MList[i].status != 'e'; i++){if (MList[i].Size >= request && MList[i].status == 'f') {if (MList[i].Size - request <= 0){MList[i].status = 'u';}else{for (j = MI_SIZE - 2; j > i; j--){MList[j + 1] = MList[j];}MList[i + 1].start = MList[i].start + request; MList[i + 1].Size = MList[i].Size - request;MList[i + 1].status = 'f';MList[i].Size = request;MList[i].status = 'u';flag = 1;}break;}}if (flag != 1 || i == MI_SIZE || MList[i].status == 'e'){printf("没有足够大小的空间分配\n");}Display();}void BadFit(){int i, j = 0, k = 0, flag = 0, request;printf("最坏适应算法:请问你要分配多大的内存\n");scanf("%d", &request);for (i = 0;i < MI_SIZE - 1 && MList[i].status != 'e';i++){if (MList[i].Size >= request && MList[i].status == 'f') {flag = 1;if (MList[i].Size > k){k = MList[i].Size;j = i;}}}i = j;if (flag == 0){printf("没有足够大小的空间分配\n");j = i;}else if (MList[i].Size - request <= 0){MList[i].status = 'u';}else{for (j = MI_SIZE - 2;j > i;j--){MList[j + 1] = MList[j];}MList[i + 1].start = MList[i].start + request;MList[i + 1].Size = MList[i].Size - request;MList[i + 1].status = 'f';MList[i].Size = request;MList[i].status = 'u';}Display();}void M_Release() //释放内存{int i, number;printf("\n请问你要释放哪一块内存:\n");scanf("%d", &number);if (MList[number].status == 'u'){MList[number].status = 'f';if (MList[number + 1].status == 'f')//右边空则合并{MList[number].Size += MList[number].Size;for (i = number + 1; i < MI_SIZE - 1 && MList[i].status != 'e'; i++) { //i后面的每一个结点整体后移if (i > 0){MList[i] = MList[i + 1];}}}if (number > 0 && MList[number - 1].status == 'f')//左边空则合并{MList[number - 1].Size += MList[number].Size;for (i = number; i < MI_SIZE - 1 && MList[i].status != 'e'; i++){MList[i] = MList[i + 1];}}}else{printf("该块内存无法正常释放\n");}Display();}void BestFit(){int i, j = 0, t, flag = 0, request;printf("最佳适应算法:请问你要分配多大的内存\n");scanf("%d", &request);t = MI_SIZE;for (i = 0; i < MI_SIZE && MList[i].status != 'e'; i++){if (MList[i].Size >= request && MList[i].status == 'f'){flag = 1;if (MList[i].Size < t){t = MList[i].Size;j = i;}}}i = j;if (flag == 0){printf("没有足够大小的空间分配\n");j = i;}else if (MList[i].Size - request <= 0){MList[i].status = 'u';}else {for (j = MI_SIZE - 2; j > i; j--){MList[j + 1] = MList[j];}MList[i + 1].start = MList[i].start + request;MList[i + 1].Size = MList[i].Size - request;MList[i + 1].status = 'f';MList[i].Size = request;MList[i].status = 'u';}Display();}int main(){int x;InitMList();while (1){printf(" \n"); printf(" 1.首次适应\n");printf(" 2.最佳适应\n");printf(" 3.最差适应\n"); printf(" 4.释放内存\n"); printf(" 5.显示内存\n"); printf(" 6.退出系统\n"); printf("请输入1-6:");scanf("%d", &x);switch (x){case 1:FirstFit();break;case 2:BestFit();break;case 3:BadFit();break;case 4:M_Release();break;case 5:Display();break;case 6:exit(0);}}return 0;}实验测试结果记录:1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:1最先适应算法:请问你要分配多大的内存10---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 使用1 10 90 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:1最先适应算法:请问你要分配多大的内存25---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 使用1 10 25 使用2 35 65 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:1最先适应算法:请问你要分配多大的内存15---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 使用1 10 25 使用2 35 15 使用3 50 50 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:1最先适应算法:请问你要分配多大的内存20---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 使用1 10 25 使用2 35 15 使用3 50 20 使用4 70 30 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:4请问你要释放哪一块内存:---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 空闲1 10 25 使用2 35 15 使用3 50 20 使用4 70 30 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:4请问你要释放哪一块内存:2---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 10 空闲1 10 25 使用2 35 15 空闲3 50 20 使用4 70 30 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:2最佳适应算法:请问你要分配多大的内存5---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 5 使用1 5 5 空闲2 10 25 使用3 35 15 空闲4 50 20 使用5 70 30 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:3最坏适应算法:请问你要分配多大的内存25---------------------------------------------------块号始地址大小状态---------------------------------------------------0 0 5 使用1 5 5 空闲2 10 25 使用3 35 15 空闲4 50 20 使用5 70 25 使用6 95 5 空闲----------------------------------------------1.首次适应2.最佳适应3.最差适应4.释放内存5.显示内存6.退出系统请输入1-6:总结与自评:总结:分区存储管理是操作系统进行内存管理的一种方式。
操作系统存储管理实验报告

操作系统存储管理实验报告一、实验目的操作系统的存储管理是计算机系统中非常重要的组成部分,它直接影响着系统的性能和资源利用率。
本次实验的目的在于深入理解操作系统中存储管理的基本原理和方法,通过实际操作和观察,掌握存储分配、回收、地址转换等关键技术,并对不同存储管理策略的性能进行分析和比较。
二、实验环境本次实验在 Windows 10 操作系统下进行,使用 Visual Studio 2019 作为编程环境,编程语言为 C++。
三、实验内容(一)固定分区存储管理1、原理固定分区存储管理将内存空间划分为若干个固定大小的分区,每个分区只能装入一道作业。
分区的大小可以相等,也可以不等。
2、实现创建一个固定大小的内存空间数组,模拟内存分区。
为每个分区设置状态标志(已分配或空闲),并实现作业的分配和回收算法。
3、实验结果与分析通过输入不同大小的作业请求,观察内存的分配和回收情况。
分析固定分区存储管理的优缺点,如内存利用率低、存在内部碎片等。
(二)可变分区存储管理1、原理可变分区存储管理根据作业的实际需求动态地划分内存空间,分区的大小和数量是可变的。
2、实现使用链表或数组来管理内存空间,记录每个分区的起始地址、大小和状态。
实现首次适应、最佳适应和最坏适应等分配算法,以及分区的合并和回收算法。
3、实验结果与分析比较不同分配算法的性能,如分配时间、内存利用率等。
观察内存碎片的产生和处理情况,分析可变分区存储管理的优缺点。
(三)页式存储管理1、原理页式存储管理将内存空间和作业都划分为固定大小的页,通过页表将逻辑地址转换为物理地址。
2、实现设计页表结构,实现逻辑地址到物理地址的转换算法。
模拟页面的调入和调出过程,处理缺页中断。
3、实验结果与分析测量页式存储管理的页面置换算法(如先进先出、最近最少使用等)的命中率,分析其对系统性能的影响。
探讨页大小的选择对存储管理的影响。
(四)段式存储管理1、原理段式存储管理将作业按照逻辑结构划分为若干个段,每个段有自己的名字和长度。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、实验目的熟悉主存的分配与回收。
理解在不同的存储管理方式下.如何实现主存空间的分配与回收。
掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方式及其实现过程。
二、实验容和要求主存的分配和回收的实现是与主存储器的管理方式有关的。
所谓分配.就是解决多道作业或多进程如何共享主存空间的问题。
所谓回收.就是当作业运行完成时将作业或进程所占的主存空间归还给系统。
可变分区管理是指在处理作业过程中建立分区.使分区大小正好适合作业的需求.并且分区个数是可以调整的。
当要装入一个作业时.根据作业需要的主存量查看是否有足够的空闲空间.若有.则按需要量分割一个分区分配给该作业;若无.则作业不能装入.作业等待。
随着作业的装入、完成.主存空间被分成许多大大小小的分区.有的分区被作业占用.而有的分区是空闲的。
实验要求使用可变分区存储管理方式.分区分配中所用的数据结构采用空闲分区表和空闲分区链来进行.分区分配中所用的算法采用首次适应算法、最佳适应算法、最差适应算法三种算法来实现主存的分配与回收。
同时.要求设计一个实用友好的用户界面.并显示分配与回收的过程。
同时要求设计一个实用友好的用户界面,并显示分配与回收的过程。
三、实验主要仪器设备和材料实验环境硬件环境:PC或兼容机软件环境:VC++ 6.0四、实验原理及设计分析某系统采用可变分区存储管理.在系统运行当然开始.假设初始状态下.可用的存空间为640KB.存储器区被分为操作系统分区(40KB)和可给用户的空间区(600KB)。
(作业1 申请130KB、作业2 申请60KB、作业3 申请100KB 、作业2 释放 60KB 、作业4 申请 200KB、作业3释放100KB、作业1 释放130KB 、作业5申请140KB 、作业6申请60KB 、作业7申请50KB)当作业1进入存后.分给作业1(130KB).随着作业1、2、3的进入.分别分配60KB、100KB.经过一段时间的运行后.作业2运行完毕.释放所占存。
此时.作业4进入系统.要求分配200KB存。
作业3、1运行完毕.释放所占存。
此时又有作业5申请140KB.作业6申请60KB.作业7申请50KB。
为它们进行主存分配和回收。
1、采用可变分区存储管理.使用空闲分区链实现主存分配和回收。
空闲分区链:使用链指针把所有的空闲分区链成一条链.为了实现对空闲分区的分配和.在每个分区的起始部分设置状态位、分区的大小和各个分区的前向指针.由状态位指示该分区是否分配出去了;同时.在分区尾部还设置有一后向指针.用来后面的分区;分区中间部分是用来存放作业的空闲存空间.当该分区分配出去后.状态位就由“0”置为“1”。
设置一个存空闲分区链.存空间分区通过空闲分区链来管理.在进行存分配时.系统优先使用空闲低端的空间。
设计一个空闲分区说明链.设计一个某时刻主存空间占用情况表.作为主存当前使用基础。
初始化空间区和已分配区说明链的值.设计作业申请队列以及作业完成后释放顺序.实现主存的分配和回收。
要求每次分配和回收后显示出空闲存分区链的情况。
把空闲区说明链的变化情况以及各作业的申请、释放情况显示打印出来。
2.采用可变分区存储管理.分别采用首次适应算法、最佳适应算法和最坏适应算法实现主存分配和回收。
3、主存空间分配(1)首次适应算法在该算法中.把主存中所有空闲区按其起始地址递增的次序排列。
在为作业分配存储空间时.从上次找到的空闲分区的下一个空闲分区开始查找.直到找到第一个能满足要求的空闲区.从中划出与请求的大小相等的存储空间分配给作业.余下的空闲区仍留在空闲区链中。
(2)最佳适应算法在该算法中.把主存中所有空闲区按其起始地址递增的次序排列。
在为作业分配存储空间时.从上次找到的空闲分区的下一个空闲分区开始查找.直到找到一个能满足要求的空闲区且该空闲区的大小比其他满足要求的空闲区都小.从中划出与请求的大小相等的存储空间分配给作业.余下的空闲区仍留在空闲区链中(3)最坏适应算法在该算法中.把主存中所有空闲区按其起始地址递增的次序排列。
在为作业分配存储空间时.从上次找到的空闲分区的下一个空闲分区开始查找.直到找到一个能满足要求的空闲区且该空闲区的大小比其他满足要求的空闲区都大.从中划出与请求的大小相等的存储空间分配给作业.余下的空闲区仍留在空闲区链中。
4、主存空间回收当一个作业执行完成撤离时.作业所占的分区应该归还给系统。
归还的分区如果与其它空闲区相邻.则应合成一个较大的空闲区.登记在空闲区说明链中.此时.相邻空闲区的合并问题.要求考虑四种情况:(1)释放区下邻空闲区(低地址邻接)(2)释放区上邻空闲区(高地址邻接)(3)释放区上下都与空闲区邻接(4)释放区上下邻都与空闲区不邻接五、程序流程图main函数里的流程图分配空间里的流程图回收空间里的流程图六、相关数据结构及关键函数说明本程序采用了一个struct free_table数据结构.里面包含分区序号(num)、起始地址(address)、分区长度(length)和分区状态(state)。
还用了线性表的双性链表存储结构(struct Node).里面包含前区指针(prior)和后继指针(next)。
一开始定义一条(含有first和end)的链.用开始指针和尾指针开创空间链表。
然后分别按三种算法进行分配和回收。
在该程序中关键函数有.sort()、allocation()、recovery()、和First_fit()、Best_fit()、Worst_fit();其中sort()函数是用来整理分区序号的.如在删序号3时.她与前面序号2相连在一起了.然后序号2中的长度总满足申请的存大小.就会在序号2中分配.然后序号在2的基础上加1.一直加.加到与原本序号3的下一个序号也就是4相等.这时sort()就开始有明显的工作了;allocation()是分配空间的.也是过渡到三个算法中的.当三个算法中满足或者不满足分配请求.都会又返回值给allocation();recovery()是用来回收存的.里面包含了四种情况相连结果.即释放区上与空闲区邻接、释放区下与空闲区邻接、释放区上下都与空闲区邻接、释放区上下都与空闲区不邻接这四种情况的结果。
七、源代码#include<stdio.h>#include<stdlib.h>#define OK 1 //完成#define ERROR 0 //出错typedef int Status;typedef struct free_table//定义一个空闲区说明表结构{int num; //分区序号long address; //起始地址long length; //分区大小int state; //分区状态}ElemType;typedef struct Node// 线性表的双向链表存储结构{ElemType data;struct Node *prior; //前趋指针struct Node *next; //后继指针}Node,*LinkList;LinkList first; //头结点LinkList end; //尾结点int flag;//记录要删除的分区序号Status Initblock()//开创带头结点的存空间链表{first=(LinkList)malloc(sizeof(Node));end=(LinkList)malloc(sizeof(Node));first->prior=NULL;first->next=end;end->prior=first;end->next=NULL;end->data.num=1;end->data.address=40;end->data.length=600;end->data.state=0;return OK;}void sort()//分区序号重新排序{Node *p=first->next,*q;q=p->next;for(;p!=NULL;p=p->next){for(q=p->next;q;q=q->next){if(p->data.num>=q->data.num){q->data.num+=1;}}}}//显示主存分配情况void show(){ int flag=0;//用来记录分区序号Node *p=first;p->data.num=0;p->data.address=0;p->data.length=40;p->data.state=1;sort();printf("\n\t\t》主存空间分配情况《\n");printf("**********************************************************\n\n"); printf("分区序号\t起始地址\t分区大小\t分区状态\n\n");while(p){printf("%d\t\t%d\t\t%d",p->data.num,p->data.address,p->data.length);if(p->data.state==0) printf("\t\t空闲\n\n");else printf("\t\t已分配\n\n");p=p->next;}printf("**********************************************************\n\n");}//首次适应算法Status First_fit(int request){//为申请作业开辟新空间且初始化Node *p=first->next;LinkList temp=(LinkList)malloc(sizeof(Node));temp->data.length=request;temp->data.state=1;p->data.num=1;while(p){if((p->data.state==0)&&(p->data.length==request)){//有大小恰好合适的空闲块p->data.state=1;return OK;break;}else if((p->data.state==0) && (p->data.length>request)) {//有空闲块能满足需求且有剩余temp->prior=p->prior;temp->next=p;temp->data.address=p->data.address;temp->data.num=p->data.num;p->prior->next=temp;p->prior=temp;p->data.address=temp->data.address+temp->data.length; p->data.length-=request;p->data.num+=1;return OK;break;}p=p->next;}return ERROR;}//最佳适应算法Status Best_fit(int request){int ch; //记录最小剩余空间Node *p=first;Node *q=NULL; //记录最佳插入位置LinkList temp=(LinkList)malloc(sizeof(Node));temp->data.length=request;temp->data.state=1;p->data.num=1;while(p) //初始化最小空间和最佳位置{if((p->data.state==0) && (p->data.length>=request) ) {if(q==NULL){q=p;ch=p->data.length-request;}else if(q->data.length > p->data.length){q=p;ch=p->data.length-request;}}p=p->next;}if(q==NULL) return ERROR;//没有找到空闲块else if(q->data.length==request){q->data.state=1;return OK;}else{temp->prior=q->prior;temp->next=q;temp->data.address=q->data.address;temp->data.num=q->data.num;q->prior->next=temp;q->prior=temp;q->data.address+=request;q->data.length=ch;q->data.num+=1;return OK;}return OK;}//最差适应算法Status Worst_fit(int request){int ch; //记录最大剩余空间Node *p=first->next;Node *q=NULL; //记录最佳插入位置LinkList temp=(LinkList)malloc(sizeof(Node));temp->data.length=request;temp->data.state=1;p->data.num=1;while(p) //初始化最大空间和最佳位置{if(p->data.state==0 && (p->data.length>=request) ) {if(q==NULL){q=p;ch=p->data.length-request;}else if(q->data.length < p->data.length){q=p;ch=p->data.length-request;}}p=p->next;}if(q==NULL) return ERROR;//没有找到空闲块else if(q->data.length==request){q->data.length=1;return OK;}else{temp->prior=q->prior;temp->next=q;temp->data.address=q->data.address;temp->data.num=q->data.num;q->prior->next=temp;q->prior=temp;q->data.address+=request;q->data.length=ch;q->data.num+=1;return OK;}return OK;}//分配主存Status allocation(int a){int request;//申请存大小printf("请输入申请分配的主存大小(单位:KB):");scanf("%d",&request);if(request<0 ||request==0){printf("分配大小不合适.请重试!");return ERROR;}switch(a){case 1: //默认首次适应算法if(First_fit(request)==OK) printf("\t****分配成功!****"); else printf("\t****存不足.分配失败!****");return OK;break;case 2: //选择最佳适应算法if(Best_fit(request)==OK) printf("\t****分配成功!****"); else printf("\t****存不足.分配失败!****");return OK;break;case 3: //选择最差适应算法if(Worst_fit(request)==OK) printf("\t****分配成功!****"); else printf("\t****存不足.分配失败!****");return OK;break;}}Status deal1(Node *p)//处理回收空间{Node *q=first;for(;q!=NULL;q=q->next){if(q==p){if(q->prior->data.state==0&&q->next->data.state!=0){q->prior->data.length+=q->data.length;q->prior->next=q->next;q->next->prior=q->prior;q=q->prior;q->data.state=0;q->data.num=flag-1;}if(q->prior->data.state!=0&&q->next->data.state==0){q->data.length+=q->next->data.length;q->next=q->next->next;q->next->next->prior=q;q->data.state=0;q->data.num=flag;}if(q->prior->data.state==0&&q->next->data.state==0) {q->prior->data.length+=q->data.length;q->prior->next=q->next;q->next->prior=q->prior;q=q->prior;q->data.state=0;q->data.num=flag-1;}if(q->prior->data.state!=0&&q->next->data.state!=0) {q->data.state=0;}}}return OK;}Status deal2(Node *p)//处理回收空间{Node *q=first;for(;q!=NULL;q=q->next){if(q==p){if(q->prior->data.state==0&&q->next->data.state!=0) {q->prior->data.length+=q->data.length;q->prior->next=q->next;q->next->prior=q->prior;q=p->prior;q->data.state=0;q->data.num=flag-1;}if(q->prior->data.state!=0&&q->next->data.state==0){q->data.state=0;}if(q->prior->data.state==0&&q->next->data.state==0) {q->prior->data.length+=q->data.length;q->prior->next=q->next;q->next->prior=q->prior;q=q->prior;q->data.state=0;q->data.num=flag-1;}if(q->prior->data.state!=0&&q->next->data.state!=0) {q->data.state=0;}}}return OK;}//主存回收Status recovery(int flag){Node *p=first;for(;p!=NULL;p=p->next){if(p->data.num==flag){if(p->prior==first){if(p->next!=end)//当前P指向的下一个不是最后一个时{if(p->next->data.state==0) //与后面的空闲块相连 {p->data.length+=p->next->data.length;p->next->next->prior=p;p->next=p->next->next;p->data.state=0;p->data.num=flag;}else p->data.state=0;}if(p->next==end)//当前P指向的下一个是最后一个时{p->data.state=0;}}//结束if(p->prior==block_first)的情况else if(p->prior!=first){if(p->next!=end){deal1(p);}else{deal2(p);}}//结束if(p->prior!=block_first)的情况}//结束if(p->data.num==flag)的情况}printf("\t****回收成功****");return OK;}//主函数void main(){int i; //操作选择标记int a;//算法选择标记printf("**********************************************************\n"); printf("\t\t用以下三种方法实现主存空间的分配\n");printf("\t(1)首次适应算法\t(2)最佳适应算法\t(3)最差适应算法\n");printf("**********************************************************\n"); printf("\n");printf("请输入所使用的存分配算法:");scanf("%d",&a);while(a<1||a>3){printf("输入错误.请重新输入所使用的存分配算法:\n");scanf("%d",&a);}switch(a){case 1:printf("\n\t****使用首次适应算法:****\n");break; case 2:printf("\n\t****使用最佳适应算法:****\n");break; case 3:printf("\n\t****使用最坏适应算法:****\n");break;}Initblock(); //开创空间表while(1){show();printf("\t1: 分配存\t2: 回收存\t0: 退出\n");printf("请输入您的操作:");scanf("%d",&i);if(i==1)allocation(a); // 分配存else if(i==2) // 存回收{printf("请输入您要释放的分区号:");scanf("%d",&flag);recovery(flag);}else if(i==0){printf("\n退出程序\n");break; //退出}else //输入操作有误{printf("输入有误.请重试!");continue;}}}八、执行结果和结果分析初始化首次适应算法:当作业1、2、3顺利分配存空间后:回收序号2里面的存:分配作业4:回收序号3里面的存(与上邻序号2相连了)回收序号1里的存(与下邻序号2相连了)继续分配(会发现总是按顺序查找满足要求的第一个空闲块.一旦发现就会分配):初始化最佳适应算法:继续分配(会发现总是查找满足要求的空闲块且其比其他空闲块长度小.一旦发现就会分配):初始化最坏适应算法:继续分配(会发现总是查找满足要求的空闲块且其比其他空闲块长度小.一旦发现就会分配):九、所遇困难的解决以及心得体会本实验我采取用一条链表同时表示空闲分区链和主存空间占用情况.因为主存总大小是固定的.把空闲分区链所表示的区域从总的存里去除就是被占用的空间的大小.这个实验还是比较简单的.但在执行过程中还是遇到了很多问题.如在回收空间的函数中.因为要考虑到四种情况.我一开始的想法是这样的:让p指向链表开头.一直等找到p所指向的分区序号等于要删除的分区序号.然后开始执行.当p->prior不是链首first时要考虑p->next是不是链尾end.然后继续考虑p的前向指针和后向指针得状态是否为空闲;等考虑完p->prior不是链首了.就进行考虑p->prior是链首的问题.然后又进行了考虑p->next是不是链尾end.然后继续考虑p的前向指针和后向指针得状态是否为空闲;等考虑完了p->prior的问题又进行考虑p->next的问题.一直这样重复了.我都不知道.当时超烦的.后来静下心重新检查自己写得程序.才知道自己写得这个函数好凌乱。