内存最佳分配实验报告
- 格式:docx
- 大小:21.16 KB
- 文档页数:5
存储器管理实验实验报告一、实验目的存储器管理是操作系统的重要组成部分,本次实验的目的在于深入理解存储器管理的基本原理和方法,通过实际操作和观察,掌握存储器分配与回收的算法,以及页面置换算法的实现和性能评估。
二、实验环境本次实验使用的操作系统为 Windows 10,编程语言为 C++,开发工具为 Visual Studio 2019。
三、实验内容与步骤(一)存储器分配与回收算法实现1、首次适应算法(1)原理:从空闲分区链的首地址开始查找,找到第一个满足需求的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态(已分配或空闲)。
当有分配请求时,从链表头部开始遍历,找到第一个大小满足需求的空闲分区。
将该分区进行分割,一部分分配给请求,剩余部分仍作为空闲分区留在链表中。
若找不到满足需求的空闲分区,则返回分配失败。
2、最佳适应算法(1)原理:从空闲分区链中选择与需求大小最接近的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态。
当有分配请求时,遍历整个链表,计算每个空闲分区与需求大小的差值。
选择差值最小的空闲分区进行分配,若有多个差值相同且最小的分区,选择其中起始地址最小的分区。
对选中的分区进行分割和处理,与首次适应算法类似。
3、最坏适应算法(1)原理:选择空闲分区链中最大的空闲分区进行分配。
(2)实现步骤:建立空闲分区链表,每个节点包含分区的起始地址、大小和状态。
当有分配请求时,遍历链表,找到最大的空闲分区。
对该分区进行分配和处理。
(二)页面置换算法实现1、先进先出(FIFO)页面置换算法(1)原理:选择在内存中驻留时间最久的页面进行置换。
(2)实现步骤:建立页面访问序列。
为每个页面设置一个进入内存的时间戳。
当发生缺页中断时,选择时间戳最早的页面进行置换。
2、最近最久未使用(LRU)页面置换算法(1)原理:选择最近一段时间内最长时间未被访问的页面进行置换。
实验报告(五)内存分配一、实验目的通过学习Minix操作系统的内存分配,加深理解操作系统内存管理的相关概念和原理。
二、准备工作注:如果熟悉准备工作内容,可忽略。
1、练习使用vi编辑器vi编辑器具有两种模式(1)命令模式通过键盘左上角ESC键进入,在该模式下可以使用编辑命令。
删除一行(连续键入两个d);删除光标处的字符(小写x);在当前光标前插入(i);在当前光标后插入(a);保存(shift+冒号,再键入w);退出编辑器(shift+冒号,再键入q);保存并且退出(shift+冒号,再键入wq);(2)编辑模式在命令模式下,通过在当前光标前插入(i)或在当前光标后插入(a),进入编辑模式。
通过键盘左上角ESC键切换到命令模式。
2、练习修改、编译和安装新操作系统(1)修改/usr/src/kernel/main.c中的announce函数cd /usr/src/kernelcp main.c main.c.backupvi main.c找到announce函数增加打印语句kprintf(“在这儿增加你想打印的语句”);保存退出vi编辑器(通过键盘左上角ESC键进入命令模式,然后shift+冒号,再键入wq)(2)编译新操作系统cd /usr/src/toolsmake image(3)安装新操作系统make install(4)用新操作系统更换旧操作系统:shutdown在boot monitor下(出现d0p0s0>时),键入boot c0d0p0重新进入新操作系统。
三、实验内容、过程与分析(一)实验内容1、学习《Operating Systems Design and Implementation》(Andrew S. Tanenbaum著,第三版)中的第4章4.8.8小节,Memory Management Utilities,内存管理。
Minix内存管理采用了动态分区分配以及首次适应算法。
内存分配实验报告内存分配实验报告一、引言内存分配是计算机科学中一个重要的概念,它涉及到操作系统、编程语言以及计算机硬件等多个方面。
在本次实验中,我们将探索不同的内存分配算法,并对它们的性能进行评估和比较。
二、实验目的1. 理解内存分配的基本原理和概念;2. 学习不同的内存分配算法,并掌握它们的优缺点;3. 通过实验对比,评估不同算法在不同场景下的性能表现。
三、实验方法1. 实验环境本次实验使用C语言编写,运行在Linux操作系统上。
实验中使用了常见的内存分配算法,包括首次适应算法、最佳适应算法和最坏适应算法。
2. 实验步骤(1)首次适应算法首次适应算法是一种简单而常用的内存分配算法。
它从内存的起始位置开始查找,找到第一个能满足分配要求的空闲块进行分配。
实验中,我们模拟了一系列内存分配请求,并记录了每次分配的时间和分配结果。
(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.实验环境准备本实验使用C语言编程,要求安装GCC编译器和Linux操作系统。
2.实验内容实验主要包括以下几个部分:a.基本内存管理创建一个进程结构体,并为其分配一定大小的内存空间。
可以通过C语言中的指针操作来模拟内存管理的过程。
b.连续分配内存算法实现两种连续分配内存的算法:首次适应算法和最佳适应算法。
首次适应算法是从低地址开始寻找满足要求的空闲块,最佳适应算法是从所有空闲块中选择最小的满足要求的块。
c.非连续分配内存算法实现分页和分段两种非连续分配内存的算法。
分页是将进程的虚拟地址空间划分为固定大小的页面,然后将页面映射到物理内存中。
分段是将进程的地址空间划分为若干个段,每个段可以是可变大小的。
3.实验结果分析使用实验中的算法和方法,可以实现对系统内存的高效管理。
通过比较不同算法的性能指标,我们可以选择合适的算法来满足系统的需求。
具体而言,连续分配内存算法中,首次适应算法适用于内存中有大量小碎片的情况,可以快速找到满足要求的空闲块。
最佳适应算法适用于内存中碎片较少的情况,可以保证最小的内存浪费。
非连续分配内存算法中,分页算法适用于对内存空间的快速分配和回收,但会带来一定的页表管理开销。
分段算法适用于对进程的地址空间进行分段管理,可以灵活地控制不同段的权限和大小。
实验中还可以通过性能测试和实际应用场景的模拟来评估算法的性能和适用性。
实验总结:本实验主要介绍了内存管理的相关概念和算法,通过编写相应的代码实现了基本内存管理和连续分配、非连续分配内存的算法。
通过实际的实验操作,加深了对内存管理的理解。
在实验过程中,我们发现不同算法适用于不同情况下的内存管理。
连续分配算法可以根据实际情况选择首次适应算法或最佳适应算法。
内存连续分配方式实验内存连续分配是操作系统中的重要概念之一、在计算机系统中,内存分配是指将进程所需的内存空间分配给其使用,同时也需要满足内存管理的要求。
内存连续分配方式是指将进程所需的内存空间连续地划分并分配给进程。
下面将介绍内存连续分配的几种方式及实验。
1.固定分区分配方式:固定分区分配方式是将整个内存空间分为若干个大小相等的分区,并为每个分区分配一个进程。
这种分配方式适用于进程数固定或进程大小相对稳定的场景。
固定分区分配方式的优点是简单易实现,缺点是可能会造成内存空间浪费,同时,当进程数或进程大小发生变化时,需要重新划分分区,性能较差。
2.动态分区分配方式:动态分区分配方式是根据进程的实际需要动态地分配内存空间。
动态分区分配方式将内存空间划分为若干个大小不等的分区,每个分区都可以独立地分配给进程使用。
当有新进程需要内存空间时,系统会根据分区空闲情况找到合适的分区进行分配。
动态分区分配方式的优点是充分利用内存空间,缺点是可能会出现内存碎片问题。
3.伙伴系统分配方式:伙伴系统分配方式是一种动态分区分配方式的改进版本。
它将内存空间划分为若干个大小相等的块,每个块大小都是2的幂。
当有新进程需要内存空间时,系统会找到与其大小最接近的空闲块进行分配。
如果找到的块大于所需大小,则将其划分为两个大小相等的块,其中一个分配给进程,另一个留作备用;如果找到的块小于所需大小,则会继续查找更大的空闲块进行分配。
伙伴系统分配方式的优点是减少了内存碎片问题,缺点是实现较为复杂。
实验设计:1.实验目的:通过实验,测试和比较不同的内存连续分配方式在不同场景下的性能和效果。
2.实验环境:使用一台具备内存管理功能的计算机,并在上面运行操作系统。
3.实验步骤:a.首先,选择一种内存连续分配方式,如固定分区分配方式。
b.根据选择的分配方式,设置相应的分区大小和数量。
c.运行一些需要内存空间的进程,并观察它们的分配情况。
d.记录每个进程所分配到的内存空间大小和位置,以及未分配的内存空间大小和位置。
一、实验目的1. 熟悉内存的基本操作,包括内存的分配、释放、读写等。
2. 掌握C语言中内存操作的相关函数,如malloc、free、memcpy等。
3. 提高对内存管理重要性的认识,了解内存泄漏的成因及预防措施。
二、实验环境1. 操作系统:Windows 102. 编译器:Visual Studio 20193. 编程语言:C语言三、实验内容1. 内存分配与释放2. 内存读写3. 内存拷贝4. 内存泄漏检测四、实验步骤1. 内存分配与释放(1)编写一个函数,使用malloc分配内存,并打印分配的内存地址。
```c#include <stdio.h>#include <stdlib.h>void test_malloc() {int p = (int )malloc(sizeof(int));if (p == NULL) {printf("Memory allocation failed.\n");return;}printf("Memory address: %p\n", p);free(p);}int main() {test_malloc();return 0;}```(2)编写一个函数,使用calloc分配内存,并打印分配的内存地址。
```c#include <stdio.h>#include <stdlib.h>void test_calloc() {int p = (int )calloc(10, sizeof(int));if (p == NULL) {printf("Memory allocation failed.\n");return;}printf("Memory address: %p\n", p);free(p);}int main() {test_calloc();return 0;}```2. 内存读写(1)编写一个函数,使用memcpy函数复制内存内容。
操作系统实验之内存管理实验报告一、实验目的内存管理是操作系统的核心功能之一,本次实验的主要目的是深入理解操作系统中内存管理的基本原理和机制,通过实际编程和模拟操作,掌握内存分配、回收、地址转换等关键技术,提高对操作系统内存管理的认识和实践能力。
二、实验环境本次实验在 Windows 操作系统下进行,使用 Visual Studio 作为编程环境,编程语言为 C++。
三、实验原理1、内存分配算法常见的内存分配算法有首次适应算法、最佳适应算法和最坏适应算法等。
首次适应算法从内存的起始位置开始查找,找到第一个满足需求的空闲分区进行分配;最佳适应算法则选择大小最接近需求的空闲分区;最坏适应算法选择最大的空闲分区进行分配。
2、内存回收算法当进程结束释放内存时,需要将其占用的内存区域回收至空闲分区链表。
回收过程中需要考虑相邻空闲分区的合并,以减少内存碎片。
3、地址转换在虚拟内存环境下,需要通过页表将逻辑地址转换为物理地址,以实现进程对内存的正确访问。
四、实验内容1、实现简单的内存分配和回收功能设计一个内存管理模块,能够根据指定的分配算法为进程分配内存,并在进程结束时回收内存。
通过模拟多个进程的内存请求和释放,观察内存的使用情况和变化。
2、实现地址转换功能构建一个简单的页式存储管理模型,模拟页表的建立和地址转换过程。
给定逻辑地址,能够正确计算出对应的物理地址。
五、实验步骤1、内存分配和回收功能实现定义内存分区的数据结构,包括起始地址、大小、使用状态等信息。
实现首次适应算法、最佳适应算法和最坏适应算法的函数。
创建空闲分区链表,初始化为整个内存空间。
模拟进程的内存请求,调用相应的分配算法进行内存分配,并更新空闲分区链表。
模拟进程结束,回收内存,处理相邻空闲分区的合并。
2、地址转换功能实现定义页表的数据结构,包括页号、页框号等信息。
给定页面大小和逻辑地址,计算页号和页内偏移。
通过页表查找页框号,结合页内偏移计算出物理地址。
一、实验目的熟悉主存的分配与回收。
理解在不同的存储管理方式下.如何实现主存空间的分配与回收。
掌握动态分区分配方式中的数据结构和分配算法及动态分区存储管理方式及其实现过程。
二、实验内容和要求主存的分配和回收的实现是与主存储器的管理方式有关的。
所谓分配.就是解决多道作业或多进程如何共享主存空间的问题。
所谓回收.就是当作业运行完成时将作业或进程所占的主存空间归还给系统。
可变分区管理是指在处理作业过程中建立分区.使分区大小正好适合作业的需求.并且分区个数是可以调整的。
当要装入一个作业时.根据作业需要的主存量查看是否有足够的空闲空间.若有.则按需要量分割一个分区分配给该作业;若无.则作业不能装入.作业等待。
随着作业的装入、完成.主存空间被分成许多大大小小的分区.有的分区被作业占用.而有的分区是空闲的。
实验要求使用可变分区存储管理方式.分区分配中所用的数据结构采用空闲分区表和空闲分区链来进行.分区分配中所用的算法采用首次适应算法、最佳适应算法、最差适应算法三种算法来实现主存的分配与回收。
同时.要求设计一个实用友好的用户界面.并显示分配与回收的过程。
同时要求设计一个实用友好的用户界面,并显示分配与回收的过程。
三、实验主要仪器设备和材料实验环境硬件环境: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运行完毕.释放所占内存。
操作系统实验报告内存分配学生学号:学生姓名:专业年级:(一)实验目的设计编写首次适应算法实现内存分配,每次从低位开始对内存进行检验分配。
(二)设计思想程序分配内存时每次从最低位开始检验是否有满足分配条件的空闲空间,有则把该进程分配到链表的最后(若在中间有足够空闲空间且与两者差大于最小分配的空间大小则分配到该空闲空间的后面,然后把原空闲空间减去已分配的大小);每次释放空间先检查所释放空间前后是否有空闲空间,有则将空间合并。
(三)主要数据结构及变量说明空间链表数据类型space:struct space{struct space *former; int address;int num; int size; int state; struct space *next;},记录内存空间相关属性;最小分配空间int size_min=10;定义空间链表为S:typedef struct space S;S的指针mem:S *mem;;数据类型struct space *former:链表头结点;数据类型struct space *next:链表尾节点;m存放系统内存空间总大小的值。
(四)流程图(五)运行结果(六)附录(代码):#include<stdio.h>#include<stdlib.h>#include <iostream.h>struct space{struct space *former;int address;int num;int size;int state;struct space *next;};typedef struct space S;S *mem;int size_min=10;int m;void init(){mem=new S;mem->size=m;mem->former=0;mem->next=0;}void alloc(S *ptr,S *assign){if(ptr->next==NULL){if(ptr->size>=assign->size){ptr->size=ptr->size-assign->size;assign->state=1;ptr->next=assign;assign->former=ptr;}else{printf("没有足够的内存空间为进程%d分配\n",assign->num);delete assign;}}else{S *previous,*current;previous=ptr;current=previous->next;while(current!=NULL){if(current->size>=assign->size&¤t->state==0){break;}previous=current;current=current->next;}if(current==NULL){if(ptr->size>=assign->size){assign->address =m-(ptr->size);ptr->size=ptr->size-assign->size;assign->state=1;assign->former=previous;previous->next=assign;}else{printf("没有足够的内存空间为进程%d分配\n",assign->num);}}else{if((current->size-assign->size)<=size_min){current->num=assign->num;current->state=1;delete assign;}else{current->size=current->size-assign->size;assign->state=1;assign->address=current->address;current->address=assign->address+assign->size;current->former=assign;assign->next=current;assign->former=previous;previous->next=assign;}}}}void printgroup(S *ptr){S *temp;temp=ptr->next;printf("内存链的状态为:\n");while(temp!=NULL){if(temp->state==0){printf(" 起始地址为:%d",temp->address);printf(" 空闲空间大小为:%d",temp->size);printf(" 内存空闲\n");}else{printf("运行的进程:%d",temp->num);printf(" 起始地址为:%d",temp->address);printf(" 分配空间大小为:%d",temp->size);printf(" 内存已分配\n");}temp=temp->next;}}void free(S *ptr,int i){S *previous,*current;previous=ptr; current=previous->next;while(current!=NULL){if(current->state==1&¤t->num==i){break;}previous=current;current=current->next;}if(current==NULL){printf("内存中没有任何进程!!!\n");}else if(current->next==NULL){if(previous->state==0){previous->size=previous->size+current->size;previous->next=NULL;}else{current->state=0;}printf("进程%d释放%d的空间\n",current->num,current->size);printgroup(mem);}else{if(previous->state==0&&(current->next)->state==0){previous->size=previous->size+current->size+(current->next)->s ize;if((current->next)->next==NULL){previous->next=NULL;}else{((current->next)->next)->former=previous;previous->next=(current->next)->next;}}else if(previous->state==0){previous->size=previous->size+current->size;(current->next)->former=previous;previous->next=current->next;}else if((current->next)->state==0){current->size=current->size+(current->next)->size;current->state=0;if((current->next)->next==NULL){previous->next=NULL;}else{((current->next)->next)->former=current;current->next=(current->next)->next;}}else{current->state=0;}printf("进程%d释放%d的空间\n",current->num,current->size);printgroup(mem);}}void Creat(int i,int temp){printf("输入进程名和大小:\n");scanf("%d",&i);scanf("%d",&temp);space *fenpei;fenpei=(S *)malloc(sizeof(space));fenpei->former=NULL;fenpei->address=0;fenpei->size=temp;fenpei->num=i;fenpei->state=0;fenpei->next=NULL;alloc(mem,fenpei);printgroup(mem);}void main(void){int i;int j,k;printf("请输入内存大小:");scanf("%d",&m);init();while(1){printf("**************************\n");printf("申请内存输入数字1\n");printf("释放内存输入数字2\n");printf("中止进程输入数字0\n");printf("**************************\n");scanf("%d",&i);if(i==1){Creat(j,k);}if(i==2){printf("输入进程名:\n");scanf("%d",&j);free(mem,j);}if(i==0){break;}}}。
代码实现如下:#include <stdio.h>#include <malloc.h>#include <stdlib.h>#define n 64 //定义内存的大小int a[n],count=0;//数组a用来保存内存使用状况1为已分配0为未分配,count用来记name数组中元素个数char name[n];//已分配内存的名称(字符类型)typedef struct linknode{char pid;int start;int length;struct linknode *left,*right;}de_node; //进程节点结构体定义//head1表示未分配内存队列头指针,head2便是已分配进程队列头指针de_node *head1,*head2=NULL;struct linknode* creat()//创建一个进程节点{int len,flag1=1;//用于表示进程是否可以创建char id;struct linknode* p;p = (de_node *)malloc(sizeof(de_node));//试图在系统内存中开辟空间创建一个进程if (p==NULL) //p为空,说明系统没有可用内存用于创建此模拟进程{ printf("系统没有足够的内存可供使用!\n");//输出return(NULL);//返回空指针}printf("请输入进程id(字符类型)和长度:");//为进程输入id和分配的长度scanf("%c %d",&id,&len);fflush(stdin);//清除输入缓存if((id>='a'&&id<='z'||id>='A'&&id<='Z')&&(len>0)){for(int i=0;i<count;i++)//判断输入的进程名,如果已使用,返回空指针,并释放p指针if(name[i]==id){printf("此名称进程已存在!!");flag1=0;//标志位为0,表示下面对p指向内容不做修改free(p);return NULL;}if(len==0) {//如果输入要分配的进程长度为0,释放p,返回空指针printf("输入长度为0!\n");free(p);return(NULL);}if(flag1){//标志位1,可以对p指向内容进行修改p->pid=id; //idp->start=0; //初始开始内存位置,在以后会修改p->length=len;//长度p->left=NULL;//左指针p->right=NULL;//右指针name[count++]=id;//将id存入数组,count自加return(p);}//返回创建的进程的地址}else {printf("输入进程格式有误\n");free(p);return (NULL);}}//分配内存空间void distribute(de_node *p){ de_node *q=head1,*temp;int flag=0;do{//do_while循法//判断当前指向的内存空间的长度是否满足p所申请的长度,大于就分配if(q->length>=p->length) {p->start=q->start;//把进程的内存开始地址指向内存的可用开始地址处q->start+=p->length;//可用地址起始改变q->length-=p->length;//可用内存长度修改for(int i=p->start;i<p->start+p->length;i++)//将已分配的内存空间全部置1 a[i]=1;flag=1;//表示内存可分配//队列不止一个进程,第一个满足条件,并且刚好分配完,修改指针指向if(q->length==0&&q->right!=q) { if(q==head1)//如果第一个满足,修改头指针指向head1=q->right;q->left->right=q->right;q->right->left=q->left;free(q);//把这个已分配完的空间指针释放}}if(flag==1)//已做完处理直接跳出循环break;if(flag==0)//当前指向的内存不满足,指向下一个,继续判断是否满足q=q->right;}while(q!=head1);//搜索一遍可用内存序列if(flag==0){//没有可用的内存printf("没有满足的内存!\n");count--;//由于创建时加1,但在分配内存时失败,把1又减掉free(p);//把这个未分配到内存的进程释放}if(flag==1){//表示上面已分配好内存,并已修改内存链表,下面修改已分配内存的进程队列temp=head2;//把已分配内存的进程队列赋值给临时指针if(temp==NULL)//如果还还没有存在的任何的进程,说明当前是第一个{ head2=p;//让头指针指向第一个进程p->left=p;//双向队列第一个左右指针都指向自己p->right=p;//双向队列第一个左右指针都指向自己}else if(temp!=NULL){//已存在队列,把当前直接链到第一个,与上面的区别是指针指向head2=p;//让头指针指向p指向的进程p->left=temp->left;//p进程左边为原来第一个的左边p->right=temp;//p进程右边指向第一个temp->left->right=p;//原来第一个的左边为ptemp->left=p;//原来第一个的左边的进程为p}}}//对进程的回收void reclaim(){ char id;int flag=0;de_node *q=head2,*p=head1;if(head2==NULL)//表示当前没有进程{ printf("已没有进程!\n");}else {//已分配内存队列如果不为空printf("输入要回收的进程id:");//输入要回收进程的idscanf("%c",&id);fflush(stdin);for(int i=0;i<count;i++)//双重循环把要回收的进程找出来,并把记录的id去掉if(name[i]==id){//判断当前的进程是否满足要求for(int j=i;j<count;j++)name[j]=name[j+1];//向前覆盖name[j+1]=NULL;//置空count--;//减一}//判断是否总共只有一个进程且是够刚好也满足条件if(q->pid==id&&q->right==q&&head2==q){ head2=NULL;//把已分配队列直接置空flag=1;//表示找到满足条件的进程}if(flag==0){//上面的都没找到do{if(q->pid==id){//如果找到if(q==head2)head2=q->right;q->left->right=q->right;//修改指针指向q->right->left=q->left;flag=1;break;}else q=q->right;}while(q!=head2);}//如果找到或是遍历一遍结束if(flag==0) printf("没有此进程号!!!\n");//没有找到满足的进程if(flag==1){//表示找到了for(int i=q->start;i<q->start+q->length;i++)//释放占有的内存a[i]=0;//接下来修改可用内存的队列,while(q->start>p->start&&p->right!=head1){//从第一个开始找到回收回来的内存开始地址大的那个队列p=p->right;}if(p==head1)//表示比第一个的开始还小,那么就要修改头地址head1=q;//其他情况不用修改头地址,只需找到应该的位置,把此进程插进去q->left=p->left;//修改指针的指向q->right=p;p->left->right=q;p->left=q;if(q->start+q->length==p->start)//可以与后面合并的情况{ q->length+=p->length;//修改指针的指向p->right->left=q;q->right=p->right;free(p);}if(q->left->start+q->left->length==q->start)//可以与前面合并的情况{ q->left->length+=q->length;//修改指针的指向q->left->right=q->right;q->right->left=q->left;free(q);}}}}//打印输出void print(){ de_node *q=head2,*p=head1;if(count==0)printf("没有进程占有内存。
成绩评定表课程设计任务书目录一、题目概述(内容及要求) (4)二、功能分析............................ 错误!未定义书签。
三、设计 (6)四、运行与测试 (7)五、总结 (17)参考文献 (18)1.设计目的1)了解多道程序系统中,多个进程并发执行的内存资源分配;2)模拟可变分区内存储管理算法实现分区管理的最佳适应分配算法;3)通过实现最佳算法来进一步了解静态分区模式的优缺点;4)掌握最佳适应分配算法,深刻了解各进程在内存中的具体分配策略。
2.总体设计3.关键技术allocate():实现内存分配,并当中调用display(pbc),以及display(S)两个函数显示内存分配完成后的空闲块链表和进程链表情况。
requireback():实现内存回收,在满足情况的条件下调动allocate()对用户社情的内存块进行回收并在当中调用display(pbc),以及display(S)两个函数显示内存分配完成后的空闲块链表和进程链表情况。
callback():按内存回收时的四种情况对内存进行回收。
display(pbc):对空闲块链表中的空闲快惊醒从小到大排序并显示空闲链情况。
display(S): 对进程链表中的进程进行从小到大排序并显示进程链情况。
main():创建并初始化空闲块链表和进程链链表,用户选择操作功能。
4.程序流程图4-1图4-2 5.主要源代码#include<stdio.h>#include<iostream.h>#include<string.h>#include<iomanip.h>const int MAXJOB=100; //定义表最大记录数typedef struct node{int start; //空闲分区的起始地址int length; //空闲分区的长度char tag[20]; //分区信息是否已分配}job;job frees[MAXJOB]; //定义空闲区表int free_quantity; //空闲区的个数job occupys[MAXJOB];//定义已分配区表int occupy_quantity; //已分配区的个数//初始化函数void initial() {int i;for(i=0;i<MAXJOB;i++){frees[i].start=-1;frees[i].length=0;strcpy(frees[i].tag,"free");occupys[i].start=-1;occupys[i].length=0;strcpy(occupys[i].tag,""); }free_quantity=0;occupy_quantity=0;}//读数据函数int readData() {FILE *fp;char fname[20];cout<<endl<<" 》》欢迎进入主存储器空间的分配与回收模拟系统《《 "<<endl; cout<<endl<<endl<<"请输入初始空闲表文件名:";cin>>fname;if((fp=fopen(fname,"r"))==NULL) //读文件cout<<endl<<" 错误,文件打不开,请检查文件名!"<<endl;else{while(!feof(fp)) //文件结束{fscanf(fp,"%d",&frees[free_quantity].start);fscanf(fp,"%d",&frees[free_quantity].length);free_quantity++; }return 1; }return 0;}//sort选择——排序void sort() {int i,j,p;for(i=0;i<free_quantity-1;i++){p=i;for(j=i+1;j<free_quantity;j++)//空闲分区按地址递增的顺序排列 { if(frees[j].start<frees[p].start){ p=j; }}if(p!=i){frees[free_quantity]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantity]; }}}//显示函数void view() {int i;cout<<endl<<"-------------------------------------------"<<endl; cout<<"当前空闲表:"<<endl;cout<<"起始地址长度状态"<<endl;for(i=0;i<free_quantity;i++){cout.setf(2);cout.width(12);cout<<frees[i].start;cout.width(10);cout<<frees[i].length;cout.width(8);cout<<frees[i].tag<<endl;}cout<<endl<<"------------------------------------------"<<endl; cout<<"当前已分配表:"<<endl;cout<<"起始地址长度占用作业名"<<endl;for(i=0;i<occupy_quantity;i++) {cout.setf(2);cout.width(12);cout<<occupys[i].start;cout.width(10);cout<<occupys[i].length;cout.width(8);cout<<occupys[i].tag<<endl; }}//最先适应分配算法void earliest() {//空闲分区按地址递增的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:"; cin>>job_name; //输入作业的名称cin>>job_length; //输入作业的长度flag=0; //分配成功与否信号for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length) {flag=1; //可以分配} }if(flag==0){cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试……"<<endl; }else{t=0;i=0;while(t==0){if(frees[i].length>=job_length)//从空闲分区表顺序查找,直到找到第一能满足其大小要求的空闲分区为止{ t=1; }i++;}i--;occupys[occupy_quantity].start=frees[i].start; //修改已分区的相关信息strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length;}else //刚好分配则空闲分区数减一{ for(j=i;j<free_quantity-1;j++){frees[j]=frees[j+1]; }free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//最优适应分配算法void excellent() {//空闲分区按大小递增的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:";cin>>job_name;cin>>job_length;flag=0;for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length){flag=1;}}if(flag==0){cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试!"<<endl; }else{t=0;i=0;while(t==0){if(frees[i].length>=job_length){t=1;}i++;}i--;for(j=0;j<free_quantity;j++){if((frees[j].length>=job_length)&&(frees[j].length<frees[i].length)) { i=j; }}occupys[occupy_quantity].start=frees[i].start;strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length; }else{for(j=i;j<free_quantity-1;j++){ frees[j]=frees[j+1]; }free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//最坏适应算法void worst() {//空闲分区按大小递减的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:";cin>>job_name;cin>>job_length;flag=0;for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length)flag=1;}if(flag==0)cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试!"<<endl;else{t=0;i=0;while(t==0){if(frees[i].length>=job_length)t=1;i++;}i--;for(j=0;j<free_quantity;j++){if((frees[j].length>=job_length)&&(frees[j].length>frees[i].length))i=j;}occupys[occupy_quantity].start=frees[i].start;strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length;}else{for(j=i;j<free_quantity-1;j++){frees[j]=frees[j+1];}free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//撤消作业void finished() {char job_name[20];int i,j,flag,p=0;int start;int length;cout<<endl<<" 请输入要撤消的作业名:"; cin>>job_name;flag=-1;for(i=0;i<occupy_quantity;i++){if(!strcmp(occupys[i].tag,job_name)){flag=i;start=occupys[i].start;length=occupys[i].length; }}if(flag==-1){cout<<"没有这个作业名"<<endl; }else{//加入空闲表for(i=0;i<free_quantity;i++){if((frees[i].start+frees[i].length)==start)//上空{ if(((i+1)<free_quantity)&&(frees[i+1].start==start+length)) { //上空且下空,不为最后一个frees[i].length=frees[i].length+frees[i+1].length+length;for(j=i+1;j<free_quantity;j++)frees[j]=frees[j+1];free_quantity--;p=1;}else{frees[i].length+=length; //上空且下不空p=1; }}if(frees[i].start==(start+length)) { //下空frees[i].start=start;frees[i].length+=length;p=1; }}//空闲中没有if(p==0){frees[free_quantity].start=start;frees[free_quantity].length=length;free_quantity++;}//删除分配表中的该作业for(i=flag;i<occupy_quantity;i++)occupys[i]=occupys[i+1];occupy_quantity--; }}void main(){ int flag=0;int t=1;int chioce=0;initial();flag=readData();while(flag==1){sort();cout<<endl<<endl;cout<<" ==========================================="<<endl; cout<<" 主存储器空间的分配与回收模拟"<<endl;cout<<" ==========================================="<<endl; cout<<" 1.首次适应算法申请空间"<<endl;cout<<" 2.最佳适应算法申请空间"<<endl;cout<<" 3.最坏适应算法申请空间"<<endl;cout<<" 4.撤消作业"<<endl;cout<<" 5.显示空闲表和分配表 "<<endl;cout<<" 0.退出"<<endl;cout<<endl<<" ——> 请选择:";cin>>chioce;switch(chioce){case 1: earliest(); break;case 2: excellent() ;break;case 3: worst() ;break;case 4: finished(); break;case 5: view(); break;case 0: flag=0; break;default: cout<<"选择错误!"<<endl; } }}//文件 fname6.运行结果及结论图6-1经验总结:程序设计时,最好将不同的功能用不同的函数实现。
第1篇一、实验目的本次实验旨在让学生深入理解内存分配的基本原理和不同分配算法,通过实际操作,提高学生对内存管理技术的掌握程度。
通过本次实验,我们希望达到以下目标:1. 熟悉内存分配的基本概念和过程;2. 掌握常见的内存分配算法,如首次适应算法、最佳适应算法和最坏适应算法;3. 理解内存分配中的碎片问题,并尝试解决;4. 培养学生的动手实践能力和问题解决能力。
二、实验内容1. 实验环境:使用C语言编写程序,运行在Linux操作系统上。
2. 实验步骤:(1)首次适应算法:从内存空间的起始位置开始查找,找到第一个满足申请大小的空闲分区,将其分配给请求者。
(2)最佳适应算法:从所有空闲分区中查找一个最小的满足申请大小的分区,将其分配给请求者。
(3)最坏适应算法:从所有空闲分区中查找一个最大的满足申请大小的分区,将其分配给请求者。
(4)解决内存碎片问题:采用紧凑算法,将所有空闲分区合并成一个连续的大空间,从而减少内存碎片。
三、实验过程1. 编写程序实现内存分配算法,包括内存初始化、申请内存、释放内存等功能。
2. 对不同分配算法进行测试,观察分配效果,分析不同算法的优缺点。
3. 分析内存碎片问题,尝试解决方法,如紧凑算法。
四、实验结果与分析1. 首次适应算法:该算法简单易实现,但可能导致内存利用率较低,且可能产生较大的内存碎片。
2. 最佳适应算法:该算法分配效果较好,内存利用率较高,但分配速度较慢。
3. 最坏适应算法:该算法分配效果较差,内存利用率较低,但分配速度较快。
4. 紧凑算法:通过合并空闲分区,减少了内存碎片,提高了内存利用率。
五、实验体会1. 通过本次实验,我们深入了解了内存分配的基本原理和不同分配算法,掌握了常见内存分配算法的优缺点。
2. 实验过程中,我们遇到了各种问题,如内存碎片问题、算法实现问题等,通过查阅资料、讨论和尝试,最终解决了这些问题,提高了我们的问题解决能力。
3. 实验使我们认识到,内存管理是操作系统中的一个重要组成部分,对计算机性能和稳定性有着重要影响。
操作系统实验报告实验[ 1 ]:主存储器空间的分配和回收姓名:何浪学号: 201306080215专业班级:计本132实验时间: 2015.5.31报告时间:2015.6.6系别:计算机系5k 10k 14k 26k 32k 512k学 院: 电气与信息工程学院实验3 主存储器空间的分配和回收一、实验内容主存储器空间的分配和回收。
二、实验目的一个好的计算机系统不仅要有一个足够容量的、存取速度高的、稳定可靠的主存储器,而且要能合理地分配和使用这些存储空间。
当用户提出申请存储器空间时,存储管理必须根据申请者的要求,按一定的策略分析主存空间的使用情况,找出足够的空闲区域分配给申请者。
当作业撤离或主动归还主存资源时,则存储管理要收回作业占用的主存空间或归还部分主存空间。
主存的分配和回收的实现与主存储器的管理方式有关的,通过本实验帮助学生理解在可变分区管理方式下应怎样实现主存空间的分配和回收。
三、实验原理模拟在可变分区管理方式下采用最先适应算法实现主存分配和回收。
(1)可变分区方式是按作业需要的主存空间大小来分割分区的。
当要装入一个作业时,根据作业需要的主存量查看是否有足够的空闲空间,若有,则按需要量分割一个分区分配给该作业;若无,则作业不能装入。
随着作业的装入、撤离,主存空间被分成许多个分区,有的分区被作业占用,而有的分区是空闲的。
例如:为了说明哪些区是空闲的,可以用来装入新作业,必须要有一张空闲区说明表,格式如下:第一栏第二栏M长度——指出从起始地址开始的一个连续空闲的长度。
状态——有两种状态,一种是“未分配”状态,指出对应的由起址指出的某个长度的区域是空闲区。
(2) 当有一个新作业要求装入主存时,必须查空闲区说明表,从中找出一个足够大的空闲区。
有时找到的空闲区可能大于作业需要量,这时应把原来的空闲区变成两部分:一部分分给作业占用;另一部分又成为一个较小的空闲区。
为了尽量减少由于分割造成的空闲区,而尽量保存高地址部分有较大的连续空闲区域,以利于大型作业的装入。
1. 理解内存分配的基本原理和方法;2. 掌握常见内存分配算法的实现过程;3. 分析不同内存分配算法的性能特点;4. 通过实验加深对内存管理机制的理解。
二、实验环境1. 操作系统:Windows 102. 编程语言:C语言3. 开发环境:Visual Studio 2019三、实验内容1. 内存分配算法本次实验主要实现了以下几种内存分配算法:(1)首次适应算法(First Fit):从空闲分区列表的头部开始查找,找到第一个足够大的分区进行分配。
(2)最佳适应算法(Best Fit):在所有空闲分区中,找到与请求大小最接近的分区进行分配。
(3)最坏适应算法(Worst Fit):在所有空闲分区中,找到最大的分区进行分配。
2. 内存分配过程实验中,我们模拟了一个简单的内存分配过程,包括以下步骤:(1)初始化内存:创建一个足够大的内存空间,并初始化为空闲状态。
(2)请求内存:模拟用户对内存的需求,以随机方式生成请求大小。
(3)内存分配:根据请求大小,选择合适的内存分配算法进行分配。
(4)内存回收:模拟用户释放内存的过程,将释放的内存空间重新标记为空闲状态。
1. 定义内存空间:创建一个足够大的数组来模拟内存空间。
2. 定义空闲分区链表:使用链表结构存储空闲分区信息,包括分区大小、起始地址等。
3. 实现内存分配算法:(1)首次适应算法:遍历空闲分区链表,找到第一个足够大的分区进行分配。
(2)最佳适应算法:遍历空闲分区链表,找到与请求大小最接近的分区进行分配。
(3)最坏适应算法:遍历空闲分区链表,找到最大的分区进行分配。
4. 实现内存回收功能:将释放的内存空间重新标记为空闲状态。
5. 测试内存分配算法:生成一系列随机请求大小,测试不同内存分配算法的性能。
五、实验结果与分析1. 首次适应算法:在请求内存时,算法效率较高,但可能会产生较多的外部碎片。
2. 最佳适应算法:在请求内存时,算法效率较低,但分配的内存空间利用率较高,外部碎片较少。
成绩评定表课程设计任务书目录No table of contents entries found.1.设计目的1)了解多道程序系统中,多个进程并发执行的内存资源分配;2)模拟可变分区内存储管理算法实现分区管理的最佳适应分配算法;3)通过实现最佳算法来进一步了解静态分区模式的优缺点;4)掌握最佳适应分配算法,深刻了解各进程在内存中的具体分配策略。
2.总体设计3.关键技术allocate():实现内存分配,并当中调用display(pbc),以及display(S)两个函数显示内存分配完成后的空闲块链表和进程链表情况。
requireback():实现内存回收,在满足情况的条件下调动allocate ()对用户社情的内存块进行回收并在当中调用display(pbc),以及display(S)两个函数显示内存分配完成后的空闲块链表和进程链表情况。
callback():按内存回收时的四种情况对内存进行回收。
display(pbc):对空闲块链表中的空闲快惊醒从小到大排序并显示空闲链情况。
display(S): 对进程链表中的进程进行从小到大排序并显示进程链情况。
main():创建并初始化空闲块链表和进程链链表,用户选择操作功能。
4.程序流程图4-1图4-2 5.主要源代码#include<stdio.h>#include<iostream.h>#include<string.h>#include<iomanip.h>const int MAXJOB=100; //定义表最大记录数typedef struct node{int start; //空闲分区的起始地址int length; //空闲分区的长度char tag[20]; //分区信息是否已分配}job;job frees[MAXJOB]; //定义空闲区表int free_quantity; //空闲区的个数job occupys[MAXJOB];//定义已分配区表int occupy_quantity; //已分配区的个数//初始化函数void initial() {int i;for(i=0;i<MAXJOB;i++){frees[i].start=-1;frees[i].length=0;strcpy(frees[i].tag,"free");occupys[i].start=-1;occupys[i].length=0;strcpy(occupys[i].tag,""); }free_quantity=0;occupy_quantity=0;}//读数据函数int readData() {FILE *fp;char fname[20];cout<<endl<<" 》》欢迎进入主存储器空间的分配与回收模拟系统《《 "<<endl; cout<<endl<<endl<<"请输入初始空闲表文件名:";cin>>fname;if((fp=fopen(fname,"r"))==NULL) //读文件cout<<endl<<" 错误,文件打不开,请检查文件名!"<<endl;else{while(!feof(fp)) //文件结束{fscanf(fp,"%d",&frees[free_quantity].start);fscanf(fp,"%d",&frees[free_quantity].length);free_quantity++; }return 1; }return 0;}//sort选择——排序void sort() {int i,j,p;for(i=0;i<free_quantity-1;i++){p=i;for(j=i+1;j<free_quantity;j++)//空闲分区按地址递增的顺序排列 { if(frees[j].start<frees[p].start){ p=j; }}if(p!=i){frees[free_quantity]=frees[i];frees[i]=frees[p];frees[p]=frees[free_quantity]; }}}//显示函数void view() {int i;cout<<endl<<"-------------------------------------------"<<endl; cout<<"当前空闲表:"<<endl;cout<<"起始地址长度状态"<<endl;for(i=0;i<free_quantity;i++){cout.setf(2);cout.width(12);cout<<frees[i].start;cout.width(10);cout<<frees[i].length;cout.width(8);cout<<frees[i].tag<<endl;}cout<<endl<<"------------------------------------------"<<endl;cout<<"当前已分配表:"<<endl;cout<<"起始地址长度占用作业名"<<endl;for(i=0;i<occupy_quantity;i++) {cout.setf(2);cout.width(12);cout<<occupys[i].start;cout.width(10);cout<<occupys[i].length;cout.width(8);cout<<occupys[i].tag<<endl; }}//最先适应分配算法void earliest() {//空闲分区按地址递增的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:";cin>>job_name; //输入作业的名称cin>>job_length; //输入作业的长度flag=0; //分配成功与否信号for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length) {flag=1; //可以分配} }if(flag==0){cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试……"<<endl;}else{t=0;i=0;while(t==0){if(frees[i].length>=job_length)//从空闲分区表顺序查找,直到找到第一能满足其大小要求的空闲分区为止{ t=1; }i++;}i--;occupys[occupy_quantity].start=frees[i].start; //修改已分区的相关信息strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length;}else //刚好分配则空闲分区数减一{ for(j=i;j<free_quantity-1;j++){frees[j]=frees[j+1]; }free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//最优适应分配算法void excellent() {//空闲分区按大小递增的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:";cin>>job_name;cin>>job_length;flag=0;for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length){flag=1;}}if(flag==0){cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试!"<<endl; }else{t=0;i=0;while(t==0){if(frees[i].length>=job_length){t=1;}i++;}i--;for(j=0;j<free_quantity;j++){if((frees[j].length>=job_length)&&(frees[j].length<frees[i].length)) { i=j; }}occupys[occupy_quantity].start=frees[i].start;strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length; }else{for(j=i;j<free_quantity-1;j++){ frees[j]=frees[j+1]; }free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//最坏适应算法void worst() {//空闲分区按大小递减的顺序排列char job_name[20];int job_length;int i,j,flag,t;cout<<endl<<" 请输入新申请内存空间的作业名和空间大小:";cin>>job_name;cin>>job_length;flag=0;for(i=0;i<free_quantity;i++){if(frees[i].length>=job_length)flag=1;}if(flag==0)cout<<endl<<" Sorry,当前没有能满足你申请长度的空闲内存,请稍候再试!"<<endl;else{t=0;i=0;while(t==0){if(frees[i].length>=job_length)t=1;i++;}i--;for(j=0;j<free_quantity;j++){if((frees[j].length>=job_length)&&(frees[j].length>frees[i].length))i=j;}occupys[occupy_quantity].start=frees[i].start;strcpy(occupys[occupy_quantity].tag,job_name);occupys[occupy_quantity].length=job_length;occupy_quantity++;if(frees[i].length>job_length){frees[i].start+=job_length;frees[i].length-=job_length;}else{for(j=i;j<free_quantity-1;j++){frees[j]=frees[j+1];}free_quantity--;cout<<endl<<" 内存空间成功!"<<endl; }}}//撤消作业void finished() {char job_name[20];int i,j,flag,p=0;int start;int length;cout<<endl<<" 请输入要撤消的作业名:"; cin>>job_name;flag=-1;for(i=0;i<occupy_quantity;i++){if(!strcmp(occupys[i].tag,job_name)){flag=i;start=occupys[i].start;length=occupys[i].length; }}if(flag==-1){cout<<"没有这个作业名"<<endl; }else{//加入空闲表for(i=0;i<free_quantity;i++){if((frees[i].start+frees[i].length)==start)//上空{ if(((i+1)<free_quantity)&&(frees[i+1].start==start+length)) { //上空且下空,不为最后一个frees[i].length=frees[i].length+frees[i+1].length+length;for(j=i+1;j<free_quantity;j++)frees[j]=frees[j+1];free_quantity--;p=1;}else{frees[i].length+=length; //上空且下不空p=1; }}if(frees[i].start==(start+length)) { //下空frees[i].start=start;frees[i].length+=length;p=1; }}//空闲中没有if(p==0){frees[free_quantity].start=start;frees[free_quantity].length=length;free_quantity++;}//删除分配表中的该作业for(i=flag;i<occupy_quantity;i++)occupys[i]=occupys[i+1];occupy_quantity--; }}void main(){ int flag=0;int t=1;int chioce=0;initial();flag=readData();while(flag==1){sort();cout<<endl<<endl;cout<<" ==========================================="<<endl; cout<<" 主存储器空间的分配与回收模拟"<<endl;cout<<" ==========================================="<<endl; cout<<" 1.首次适应算法申请空间"<<endl;cout<<" 2.最佳适应算法申请空间"<<endl;cout<<" 3.最坏适应算法申请空间"<<endl;cout<<" 4.撤消作业"<<endl;cout<<" 5.显示空闲表和分配表 "<<endl;cout<<" 0.退出"<<endl;cout<<endl<<" ——> 请选择:";cin>>chioce;switch(chioce){case 1: earliest(); break;case 2: excellent() ;break;case 3: worst() ;break;case 4: finished(); break;case 5: view(); break;case 0: flag=0; break;default: cout<<"选择错误!"<<endl; } } }//文件 fname6.运行结果及结论图6-1经验总结:程序设计时,最好将不同的功能用不同的函数实现。
一.实验名称
模拟实现动态分区存储管理
二.实验要求
编写程序实现动态分区存储管理方式的主存分配与回收。
具体内容包括:先确定主存空间分配表;然后采用最优适应算法完成主存空间的分配与回收;最后编写主函数对所做工作进行测试。
三.解决方案
实现动态分区的分配与回收,主要考虑两个问题:第一,设计记录主存使用情况的数据结构,用来记录空闲区和作业占用的区域;第二,在该数据结构基础上设计主存分配算法和主存回收算法。
由于动态分区的大小是由作业需求量决定的,故分区的长度预先不能固定,且分区的个数也随主存分配和回收变动。
总之,所有分区的情况随时可能发生变化,数据表格的设计必须和这个特点相适应。
由于分区长度不同,因此设计的表格应该包括分区在主存中的起始地址和长度。
由于分配时,空闲区有时会变成两个分区(空闲区和已分配区),回收主存分区时,可能会合并空闲区,这样如果整个主存采用一张表格记录已分配区和空闲区,就会使表格操作繁琐。
主存分配时查找空闲区进行分配,然后填写已分配区表,主要操作在空闲区。
由此可见,主存的分配与回收主要是对空闲区的操作。
这样为了便于对主存空间的分配与回收,可建立两张分区表记录主存使用情况:“已分配区表”记录作业占用分区,“空闲区表”记录空闲区。
然后在数据结构上进行主存的分配,其主存分配算法采用最优适应算法,即按祖业要求挑选一个能满足作业要求的最小空闲区分配。
具体实现时,把空闲区按长度以某种方式(递增方式)登记在“空闲区表”中,分配时顺序查找“空闲区表”,查到的第一个空闲区就是满足作业要求的最小分区。
在实现回收时,先在“已分配区表”中找到将作业归还的区域,且变为空,检查“空闲区”表中未分配区域,查找是否有相邻空闲区,最后合并空闲区,修改“空闲区表”。
设计程序时可选择进行主存分配或主存回收,所需参数为:若是主存分配。
输入作业名和所需主存空间大小;若是回收,输入回收作业的作业名,以循环进行主存分配和回收。
四.实验代码
#include <stdio.h>
#include <stdlib.h>
#define n 10 /*定义系统允许的最大作业数*/
#define m 10 /*定义系统允许的空闲区表最大值*/
#define minisize 100
struct /*已分配区表的定义*/
{ float address;
float length;
int flag;
}used_table[n];
struct
{float address;
float length;
int flag;
}free_table[m];
void allocate(char J,float xk) /*主存分配函数开始*/ {int i,k;
float ad;
k=-1;
for(i=0;i<m;i++)
;
;
;
if(k==-1)
{
printf("无可用空闲区\n");
return ;
}
/*进行最优分配*/
if(free_table[k].length-xk<=minisize)
{free_table[k].flag=0;
ad=free_table[k].address;
xk=free_table[k].length;
}
else
{ ;
;
}
/*修改已分配区表*/ i=0;
while(used_table[i].flag!=0&&i<n)
i++;
if(i>=n)
{printf("无表目填写已分分区,错误\n");
if(free_table[k].flag==0)
free_table[k].flag=1;
else
free_table[k].length=free_table[k].length+xk;
return;
}
else
{used_table[i].address=ad;
used_table[i].length=xk;
used_table[i].flag=J;
}
return;
}
void reclaim(char J)
{int i,k,j,s,t;
float S,L;
s=0;
while((used_table[s].flag!=J||used_table[s].flag==0)&&s<n)
s++;
if(s>=n)
{printf("找不到该作业\n");
return ;
}
used_table[s].flag=0;
S=used_table[s].address;
L=used_table[s].length;
j=-1;k=-1;i=0;
while(i<m&&(j==-1||k==-1))
{
{ ;
;
}
i++;
}
if(k!=-1)
if(j!=-1)
{free_table[k].length=free_table[j].length+free_table[k].length+L;
free_table[j].flag=0;
}
else
free_table[k].length=free_table[k].length+L;
else
if(j!=-1)
{free_table[j].address=S;
free_table[j].length=free_table[j].length+L;
}
else
{t=0;
while(free_table[t].flag==1&&t<m)
t++;
if(t>=m)
{printf("主存空闲区表没有空闲,回收空间失败\n");
used_table[s].flag=J;
return;
}
free_table[t].address=S;
free_table[t].length=L;
free_table[t].flag=1;
}
return;}
int main()
{
float xk;
char J;
/*空闲区表初始化*/
free_table[0].address=10240;
free_table[0].length=102400;
free_table[0].flag=1;
int i;
for(i=1;i<m;i++)
free_table[i].flag=0;
/*已分配区表初始化*/
for(i=0;i<n;i++)
used_table[i].flag=0;
while(1)
{printf("选择功能项(0-退出,1-分配主存,2-回收主存,3-显示主存)\n"); printf("选择功能项(0~3):");
int a;
scanf("%d",&a);
switch(a)
{case 0:exit(0);
case 1:
printf("输入作业名J和作业所需长度xk:");
scanf("%*c%c%f",&J,&xk);
allocate(J,xk); /*分配主存空间*/
break;
case 2:
printf("输入要回收分区的作业名\n");
scanf("%*c%c",&J);
reclaim(J); /*回收主存空间*/
break;
case 3:
printf("输出空闲区表:\n起始地址分区长度标志\n");
for(i=0;i<m;i++)
printf("%5.0f%10.0f%6d\n",free_table[i].address,free_table[i].length,
free_table[i].flag);
printf("按任意键,输出已分配区表\n");
getchar();
printf("输出已分配区表:\n起始地址分区长度标志\n");
for(i=0;i<n;i++)
if(used_table[i].flag!=0)
printf("%6.0f%9.0f%6c\n",used_table[i].address,used_table[i].length,
used_table[i].flag);
else
printf("%6.0f%9.0f%6d\n",used_table[i].address,used_table[i].length,
used_table[i].flag);
break;
default:printf("没有该选项\n");
}
}
return 0;
} /*主函数结束*/
五.实验结果。