操作系统实验三 存储管理

news2024/12/31 2:13:54

实验三 存储管理

一、实验目的

通过实验使学生了解可变式分区管理使用的主要数据结构,分配、回收的主要技术,了解最优适应分配、最坏适应分配、最先适应分配和循环适应分配等分配算法。基本能达到下列具体的目标:

  1. 掌握初步进程在内存中的映像所需要的内存需求。
  2. 内存的最先分配算法首先实现,再逐步完成最优和最坏的分配算法。

二、实验内容

  1. 在进程管理的基础上实现内存分配和回收。
  2. 学生了解实验目的,画出流程框图。
  3. 复习单向链操作编程,编写全部程序。能够实现多种分配算法。
  4. 创建和撤消进程时,完成内存的分配和回收操作,必须可以显示空闲内存块队列状态。注意回收内存时,空闲块的合并操作。
  5. 学生要在上一次实验的基础上对队列的删除、插入进一步熟练。
  1. 程序设计(原理、数据结构设计、流程图)

1. 原理

该程序实现了一个简单的内存管理器,支持多种内存分配策略(如首次适应、最佳适应、最坏适应和下一个适应)。内存管理器通过链表结构管理空闲内存块,允许动态分配和释放内存。

2. 数据结构设计

MemoryBlock: 结构体表示一个内存块,包含起始地址、大小和指向下一个内存块的指针。

MemoryManager: 类管理内存块的分配和释放,维护一个空闲内存块的链表。

  1. 流程图

(2)核心函数

// ... existing code ...

int allocate(int size, const std::string& strategy) {

    if (size <= 0) return -1;

    if (strategy == "first_fit") {

        return firstFitAllocate(size);

    }

    else if (strategy == "best_fit") {

        return bestFitAllocate(size);

    }

    else if (strategy == "worst_fit") {

        return worstFitAllocate(size);

    }

    else if (strategy == "next_fit") {

        return nextFitAllocate(size);

    }

    return -1;

}

// ... existing code ...

void deallocate(int start, int size) {

    MemoryBlock* newBlock = new MemoryBlock(start, size);

    MemoryBlock* current = freeList;

    MemoryBlock* prev = nullptr;

    // 找到插入点

    while (current && current->start < start) {

        prev = current;

        current = current->next;

    }

    // 插入新的空闲块

    if (prev) {

        prev->next = newBlock;

    }

    else {

        freeList = newBlock;

    }

    newBlock->next = current;

    // 合并相邻的空闲块

    mergeFreeBlocks();

}

// ... existing code ...

private:

int firstFitAllocate(int size) {

    MemoryBlock* current = freeList;

    while (current) {

        if (current->size >= size) {

            int start = current->start;

            current->start += size;

            current->size -= size;

            if (current->size == 0) {

                // 如果当前块被完全分配,移除它

                if (current == freeList) {

                    freeList = current->next;

                }

                else {

                    MemoryBlock* prev = freeList;

                    while (prev->next != current) {

                        prev = prev->next;

                    }

                    prev->next = current->next;

                }

                delete current;

            }

            return start; // 返回分配的起始地址

        }

        current = current->next;

    }

    return -1; // 分配失败

}

// ... existing code ...

allocate 函数根据用户选择的策略调用相应的分配函数。

deallocate 函数负责释放指定内存块并合并相邻的空闲块。

firstFitAllocate 函数实现了首次适应算法,查找第一个足够大的空闲块进行分配。

(3)测试截图

源码:

#include <iostream>
#include <vector>
#include <limits>

struct MemoryBlock {
    int start; // 内存块的起始地址
    int size;  // 内存块的大小
    MemoryBlock* next; // 指向下一个内存块的指针

    MemoryBlock(int s, int sz) : start(s), size(sz), next(nullptr) {}
};


class MemoryManager {
private:
    MemoryBlock* freeList; // 空闲内存块链表
    int totalSize; // 总内存大小

public:
    MemoryManager(int size) : totalSize(size) {
        freeList = new MemoryBlock(0, size); // 初始化一个大的空闲块
    }

    ~MemoryManager() {
        // 释放内存块
        while (freeList) {
            MemoryBlock* temp = freeList;
            freeList = freeList->next;
            delete temp;
        }
    }

    void printFreeList() {
        std::cout << "Free memory blocks:\n";
        MemoryBlock* current = freeList;
        while (current) {
            std::cout << "Start: " << current->start << ", Size: " << current->size << "\n";
            current = current->next;
        }
    }

    int allocate(int size, const std::string& strategy) {
        if (size <= 0) return -1;

        if (strategy == "first_fit") {
            return firstFitAllocate(size);
        }
        else if (strategy == "best_fit") {
            return bestFitAllocate(size);
        }
        else if (strategy == "worst_fit") {
            return worstFitAllocate(size);
        }
        else if (strategy == "next_fit") {
            return nextFitAllocate(size);
        }
        return -1;
    }

    void deallocate(int start, int size) {
        // 释放内存块并合并空闲块
        MemoryBlock* newBlock = new MemoryBlock(start, size);
        MemoryBlock* current = freeList;
        MemoryBlock* prev = nullptr;

        // 找到插入点
        while (current && current->start < start) {
            prev = current;
            current = current->next;
        }

        // 插入新的空闲块
        if (prev) {
            prev->next = newBlock;
        }
        else {
            freeList = newBlock;
        }
        newBlock->next = current;

        // 合并相邻的空闲块
        mergeFreeBlocks();
    }

private:
    int firstFitAllocate(int size) {
        MemoryBlock* current = freeList;
        while (current) {
            if (current->size >= size) {
                int start = current->start;
                current->start += size;
                current->size -= size;

                if (current->size == 0) {
                    // 如果当前块被完全分配,移除它
                    if (current == freeList) {
                        freeList = current->next;
                    }
                    else {
                        MemoryBlock* prev = freeList;
                        while (prev->next != current) {
                            prev = prev->next;
                        }
                        prev->next = current->next;
                    }
                    delete current;
                }
                return start; // 返回分配的起始地址
            }
            current = current->next;
        }
        return -1; // 分配失败
    }

    int bestFitAllocate(int size) {
        MemoryBlock* current = freeList;
        MemoryBlock* bestFit = nullptr;
        MemoryBlock* bestFitPrev = nullptr;

        // 找到最适合的块
        while (current) {
            if (current->size >= size) {
                if (!bestFit || current->size < bestFit->size) {
                    bestFit = current;
                    bestFitPrev = nullptr;
                }
            }
            current = current->next;
        }

        if (bestFit) {
            int start = bestFit->start;
            bestFit->start += size;
            bestFit->size -= size;

            if (bestFit->size == 0) {
                // 如果当前块被完全分配,移除它
                if (bestFit == freeList) {
                    freeList = bestFit->next;
                }
                else {
                    MemoryBlock* prev = freeList;
                    while (prev->next != bestFit) {
                        prev = prev->next;
                    }
                    prev->next = bestFit->next;
                }
                delete bestFit;
            }
            return start; // 返回分配的起始地址
        }
        return -1; // 分配失败
    }

    int worstFitAllocate(int size) {
        MemoryBlock* current = freeList;
        MemoryBlock* worstFit = nullptr;
        MemoryBlock* worstFitPrev = nullptr;

        // 找到最坏适合的块
        while (current) {
            if (current->size >= size) {
                if (!worstFit || current->size > worstFit->size) {
                    worstFit = current;
                    worstFitPrev = nullptr;
                }
            }
            current = current->next;
        }

        if (worstFit) {
            int start = worstFit->start;
            worstFit->start += size;
            worstFit->size -= size;

            if (worstFit->size == 0) {
                // 如果当前块被完全分配,移除它
                if (worstFit == freeList) {
                    freeList = worstFit->next;
                }
                else {
                    MemoryBlock* prev = freeList;
                    while (prev->next != worstFit) {
                        prev = prev->next;
                    }
                    prev->next = worstFit->next;
                }
                delete worstFit;
            }
            return start; // 返回分配的起始地址
        }
        return -1; // 分配失败
    }

    int nextFitAllocate(int size) {
        static MemoryBlock* lastAllocated = nullptr; // 记录上次分配的位置
        MemoryBlock* current = lastAllocated ? lastAllocated : freeList;

        while (current) {
            if (current->size >= size) {
                int start = current->start;
                current->start += size;
                current->size -= size;

                if (current->size == 0) {
                    // 如果当前块被完全分配,移除它
                    if (current == freeList) {
                        freeList = current->next;
                    }
                    else {
                        MemoryBlock* prev = freeList;
                        while (prev->next != current) {
                            prev = prev->next;
                        }
                        prev->next = current->next;
                    }
                    delete current;
                }
                lastAllocated = current; // 更新上次分配的位置
                return start; // 返回分配的起始地址
            }
            current = current->next;
        }

        // 如果没有找到,继续从头开始搜索
        current = freeList;
        while (current) {
            if (current->size >= size) {
                int start = current->start;
                current->start += size;
                current->size -= size;

                if (current->size == 0) {
                    // 如果当前块被完全分配,移除它
                    if (current == freeList) {
                        freeList = current->next;
                    }
                    else {
                        MemoryBlock* prev = freeList;
                        while (prev->next != current) {
                            prev = prev->next;
                        }
                        prev->next = current->next;
                    }
                    delete current;
                }
                lastAllocated = current; // 更新上次分配的位置
                return start; // 返回分配的起始地址
            }
            current = current->next;
        }

        return -1; // 分配失败
    }

private:
    void mergeFreeBlocks() {
        if (!freeList) return; // 如果空闲列表为空,直接返回

        MemoryBlock* current = freeList;
        MemoryBlock* nextBlock = current->next;

        while (nextBlock) {
            // 情况 1: 前空后不空
            if (current->start + current->size == nextBlock->start) {
                // 合并当前块和下一个块
                current->size += nextBlock->size; // 合并大小
                current->next = nextBlock->next; // 跳过下一个块
                delete nextBlock; // 释放内存
                nextBlock = current->next; // 更新下一个块
            }
            // 情况 2: 前不空后空
            else if (current->start + current->size < nextBlock->start) {
                // 当前块和下一个块不相邻,直接移动到下一个块
                current = nextBlock; // 移动到下一个块
                nextBlock = nextBlock->next; // 更新下一个块
            }
            // 情况 3: 前后都空
            else {
                // 这种情况在当前逻辑中不需要特别处理,因为我们只处理相邻块的合并
                // 继续移动到下一个块
                current = nextBlock; // 移动到下一个块
                nextBlock = nextBlock->next; // 更新下一个块
            }
        }
    }

};

int main() {
    MemoryManager memoryManager(100); // 创建内存管理器,总内存为100

    std::string strategy;
    while (true) {
        std::cout << "输入想要的分配算法 (first_fit, best_fit, worst_fit, next_fit) or 'exit' to quit: ";
        std::cin >> strategy;
        if (strategy == "exit") break;

        int size;
        std::cout << "输入要分配的内存大小 ";
        std::cin >> size;

        int address = memoryManager.allocate(size, strategy);
        if (address != -1) {
            std::cout << "分配的内存位于: " << address << "\n";
        }
        else {
            std::cout << "分配失败!\n";
        }
        memoryManager.printFreeList(); // 打印空闲内存块状态

        std::cout << "输入要取消分配的大小: ";
        std::cin >> size;
        memoryManager.deallocate(address, size); // 释放内存
        memoryManager.printFreeList(); // 打印空闲内存块状态
    }

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2267464.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

40.2 预聚合和prometheus-record使用

本节重点介绍 : downsample降采样可以降低查询数据量 prometheus原生不支持downsample 实时查询/聚合 VS 预查询/聚合的优缺点 实时查询/聚合条件随意组合&#xff0c;性能差预查询/聚合 性能好&#xff0c;聚合条件需要提前定义 prometheus的预查询/聚合配置举例 downsample…

win11中win加方向键失效的原因

1、可能是你把win键锁了&#xff1a; 解决办法&#xff1a;先按Fn键&#xff0c;再按win键 2、可能是可能是 贴靠窗口设置 中将贴靠窗口关闭了&#xff0c;只需要将其打开就好了

【Rust自学】7.4. use关键字 Pt.2 :重导入与换国内镜像源教程

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 7.4.1. 使用pub use重新导入名称 使用use将路径导入作用域内后。该名称在词作用域内是私有的。 以上一篇文章的代码为例&#xff1a; m…

算法练习——模拟题

前言&#xff1a;模拟题的特点在于没有什么固定的技巧&#xff0c;完全考验自己的代码能力&#xff0c;因此有助于提升自己的代码水平。如果说一定有什么技巧的话&#xff0c;那就是有的模拟题能够通过找规律来简化算法。 一&#xff1a;替换所有问号 题目要求&#xff1a; 解…

三层交换机配置

✍作者&#xff1a;柒烨带你飞 &#x1f4aa;格言&#xff1a;生活的情况越艰难&#xff0c;我越感到自己更坚强&#xff1b;我这个人走得很慢&#xff0c;但我从不后退。 &#x1f4dc;系列专栏&#xff1a;网路安全入门系列 目录 一&#xff0c;三层交换二&#xff0c;实验案…

TCP-UDP调试工具推荐:Socket通信测试教程(附详细图解)

前言 在网络编程与应用开发中&#xff0c;调试始终是一项不可忽视的重要环节。尤其是在涉及TCP/IP、UDP等底层网络通信协议时&#xff0c;如何确保数据能够准确无误地在不同节点间传输&#xff0c;是许多开发者关注的核心问题。 调试的难点不仅在于定位连接建立、数据流控制及…

登录时的校验Token接口开发(Interceptor)

// 拦截器校验所有非登录请求时的token&#xff0c;校验成功之后解析出用户信息存入ThreadLocal中便于本次请求中共享该用户的信息&#xff0c;这个信息只能在本线程中拿到 一、需求分析 在用户登录后的请求交互中&#xff0c;Token 的校验是保障用户身份合法性和数据安全的重…

Hyper-V如何将文件复制到虚拟机

创建Hyper-V共享文件夹 通过创建共享文件夹的方式&#xff0c;能够帮助我们在主机与虚拟机之间轻松地进行数据交换共享&#xff0c;那么具体该如何通过网络共享来将文件复制到虚拟机呢&#xff1f;请您接着往下看。 步骤1. 在Hyper-V主机中创建一个文件夹&#xff0c;并将您想…

Linux(Centos 7.6)yum源配置

yum是rpm包的管理工具&#xff0c;可以自动安装、升级、删除软件包的功能&#xff0c;可以自动解决软件包之间的依赖关系&#xff0c;使得用户更方便软件包的管理。要使用yum必须要进行配置&#xff0c;个人将其分为三类&#xff0c;本地yum源、局域网yum源、第三方yum源&#…

go语言中zero框架项目日志收集与配置

在 GoZero 项目中&#xff0c;日志收集和配置是非常重要的&#xff0c;尤其是在分布式系统中&#xff0c;日志可以帮助开发人员追踪和排查问题。GoZero 提供了灵活的日志系统&#xff0c;能够方便地进行日志的配置和管理。 以下是如何在 GoZero 项目中进行日志收集与配置的基本…

第4章 共享内存范式:基于R(Rdsm)的简单介绍

第4章 4.1 是什么被共享了&#xff1f; 4.1.1 全局变量 4.1.2 局部变量&#xff1a;栈结构 4.3 共享内存编程的高级介绍&#xff1a;Rdsm包 4.3.1 使用共享内存 4.4 示例&#xff1a;矩阵乘法 4.4.1 代码 4.4.2 分析 4.4.3 代码 4.4.4 详解我们数据的共享本质 4.4.5 计时…

optuna和 lightgbm

文章目录 optuna使用1.导入相关包2.定义模型可选参数3.定义训练代码和评估代码4.定义目标函数5.运行程序6.可视化7.超参数的重要性8.查看相关信息9.可视化的一个完整示例10.lightgbm实验 optuna使用 1.导入相关包 import torch import torch.nn as nn import torch.nn.functi…

SD ComfyUI工作流 对人物图像进行抠图并替换背景

文章目录 人物抠图与换背景SD模型Node节点工作流程工作流下载效果展示人物抠图与换背景 此工作流旨在通过深度学习模型完成精确的人物抠图及背景替换操作。整个流程包括图像加载、遮罩生成、抠图处理、背景替换以及最终的图像优化。其核心基于 SAM(Segment Anything Model)与…

【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、求平方根的迭代公式 1. 原理 2. 代码实现示例 二、绝对值函数fabs() 1. 函数介绍 2. 代码示例 三、循环语句 1. for循环 2. while循环 3. do - while循环 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&…

程序猿成长之路之设计模式篇——结构型设计模式

本篇开始介绍结构型设计模式 前言 与创建型设计模式用于创建对象不同&#xff0c;结构型设计模式通过结构化的方式实现功能的扩展和解耦&#xff0c;通过对象的组合、聚合、继承和接口等机制来定义对象之间的关系&#xff0c;从而实现松耦合和灵活性。 常见的结构性设计模式&…

低代码开源项目Joget的研究——Joget8社区版安装部署

大纲 环境准备安装必要软件配置Java配置JAVA_HOME配置Java软链安装三方库 获取源码配置MySql数据库创建用户创建数据库导入初始数据 配置数据库连接配置sessionFactory&#xff08;非必须&#xff0c;如果后续保存再配置&#xff09;编译下载tomcat启动下载aspectjweaver移动jw…

数据库的概念和操作

目录 1、数据库的概念和操作 1.1 物理数据库 1. SQL SERVER 2014的三种文件类型 2. 数据库文件组 1.2 逻辑数据库 2、数据库的操作 2.1 T-SQL的语法格式 2.2 创建数据库 2.3 修改数据库 2.4 删除数据库 3、数据库的附加和分离 1、数据库的概念和操作 1.1 物理数据库…

React中最优雅的异步请求

给大家分享在React19中使用useSuspense处理异步请求为什么是被认为最优雅的解决方案 一. 传统方案 解决异步请求的方案中&#xff0c;我们要处理至少两个最基本的逻辑 正常的数据显示数据加载的UI状态 例如&#xff1a; export default function Index(){const [content, …

基于Bregman的交替方向乘子法

目录标题 ADMM方法简介Bregman散度Bregman ADMM的原理主要优势代码示例&#xff1a;各个符号的解释&#xff1a;**梯度的几何含义**&#xff1a;具体数学公式&#xff1a;**应用示例**&#xff1a;**ADMM的标准形式&#xff1a;****ADMM中的变量角色&#xff1a;****ADMM中的更…

`we_chat_union_id IS NOT NULL` 和 `we_chat_union_id != ‘‘` 这两个条件之间的区别

文章目录 1、什么是空字符串&#xff1f;2、两个引号之间加上空格 好的&#xff0c;我们来详细解释一下 we_chat_union_id IS NOT NULL 和 we_chat_union_id ! 这两个条件之间的区别&#xff0c;以及它们在 SQL 查询中的作用&#xff1a; 1. we_chat_union_id IS NOT NULL 含…