【CS.OS】堆管理算法:不同的堆分配和管理算法

news2024/9/19 10:51:30

1000.5.CS.OS.1.3-基础-内存管理-堆管理算法-Created: 2024-06-09.Sunday10:41
在这里插入图片描述

文章目录

      • 1 内存分配算法概述
        • 1.1 首次适应(First-Fit)
        • 1.2 最佳适应(Best-Fit)
      • 2 伙伴系统(Buddy System)
    • 3 总结
    • References

在操作系统和程序设计中,内存管理是一个至关重要的环节。不同的堆分配和管理算法,如首次适应(first-fit)、最佳适应(best-fit)和伙伴系统(buddy system),在内存分配和管理中发挥着重要作用。这篇文章将深入探讨这些算法,并通过示例代码展示其实现。

1 内存分配算法概述

内存分配算法用于动态地分配和释放内存,以便程序能够高效地使用系统资源。以下是一些常见的堆分配和管理算法:

1.1 首次适应(First-Fit)

首次适应算法是一种简单且快速的内存分配算法。它从头开始扫描内存分区表,找到第一个足够大的空闲块,并分配给请求的进程。

优点:

  • 快速:由于从头开始扫描,通常能迅速找到合适的空闲块。
  • 简单:实现和理解都较为简单。

缺点:

  • 内存碎片:容易产生外部碎片,导致内存利用率下降。

示例代码:

#include <iostream>
#include <vector>

struct Block {
    int size;
    bool free;
    Block(int s) : size(s), free(true) {}
};

class FirstFitAllocator {
public:
    FirstFitAllocator(std::vector<int> blockSizes) {
        for (int size : blockSizes) {
            blocks.push_back(Block(size));
        }
    }

    void* allocate(int requestSize) {
        for (Block& block : blocks) {
            if (block.free && block.size >= requestSize) {
                block.free = false;
                return &block;
            }
        }
        return nullptr; // Allocation failed
    }

    void deallocate(void* ptr) {
        Block* block = static_cast<Block*>(ptr);
        block->free = true;
    }

private:
    std::vector<Block> blocks;
};

int main() {
    FirstFitAllocator allocator({100, 500, 200, 300, 600});
    void* ptr1 = allocator.allocate(150);
    void* ptr2 = allocator.allocate(100);
    allocator.deallocate(ptr1);
    void* ptr3 = allocator.allocate(50);
    return 0;
}

1.2 最佳适应(Best-Fit)

最佳适应算法通过扫描整个内存分区表,找到最接近请求大小的空闲块进行分配。这种方法尽量减少剩余的空闲块,降低外部碎片的产生。

优点:

  • 内存利用率高:通过分配最接近大小的空闲块,减少了外部碎片。
  • 有效:在内存资源紧张的情况下表现较好。

缺点:

  • 扫描时间长:需要扫描整个内存分区表,可能导致分配时间较长。

示例代码:

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

struct Block {
    int size;
    bool free;
    Block(int s) : size(s), free(true) {}
};

class BestFitAllocator {
public:
    BestFitAllocator(std::vector<int> blockSizes) {
        for (int size : blockSizes) {
            blocks.push_back(Block(size));
        }
    }

    void* allocate(int requestSize) {
        int bestFitIndex = -1;
        int minDiff = std::numeric_limits<int>::max();

        for (int i = 0; i < blocks.size(); ++i) {
            if (blocks[i].free && blocks[i].size >= requestSize) {
                int diff = blocks[i].size - requestSize;
                if (diff < minDiff) {
                    minDiff = diff;
                    bestFitIndex = i;
                }
            }
        }

        if (bestFitIndex != -1) {
            blocks[bestFitIndex].free = false;
            return &blocks[bestFitIndex];
        }
        return nullptr; // Allocation failed
    }

    void deallocate(void* ptr) {
        Block* block = static_cast<Block*>(ptr);
        block->free = true;
    }

private:
    std::vector<Block> blocks;
};

int main() {
    BestFitAllocator allocator({100, 500, 200, 300, 600});
    void* ptr1 = allocator.allocate(150);
    void* ptr2 = allocator.allocate(100);
    allocator.deallocate(ptr1);
    void* ptr3 = allocator.allocate(50);
    return 0;
}

2 伙伴系统(Buddy System)

伙伴系统是一种平衡了首次适应和最佳适应优点的内存分配算法。它将内存分割成大小为2的幂次方的块,当需要分配内存时,会找到最小的满足请求的块。如果块大小过大,会将其分割成两个“伙伴”块,并继续分配。

优点:

  • 内存碎片少:由于采用幂次方块,容易合并相邻空闲块,减少碎片。
  • 分配和释放效率高:通过伙伴系统,分配和释放操作较为高效。

缺点:

  • 内存浪费:有时会由于块大小限制,导致内存浪费。

示例代码:

#include <iostream>
#include <vector>
#include <cmath>

class BuddyAllocator {
public:
    BuddyAllocator(int size) {
        int n = std::ceil(std::log2(size));
        maxSize = 1 << n;
        freeBlocks.resize(n + 1);
        freeBlocks[n].push_back(0);
    }

    void* allocate(int size) {
        int n = std::ceil(std::log2(size));
        for (int i = n; i < freeBlocks.size(); ++i) {
            if (!freeBlocks[i].empty()) {
                int block = freeBlocks[i].back();
                freeBlocks[i].pop_back();
                while (i > n) {
                    --i;
                    int buddy = block ^ (1 << i);
                    freeBlocks[i].push_back(buddy);
                }
                return reinterpret_cast<void*>(block * minBlockSize);
            }
        }
        return nullptr; // Allocation failed
    }

    void deallocate(void* ptr) {
        int block = reinterpret_cast<int>(ptr) / minBlockSize;
        int size = 1;
        while (true) {
            int buddy = block ^ size;
            auto it = std::find(freeBlocks[std::log2(size)].begin(), freeBlocks[std::log2(size)].end(), buddy);
            if (it == freeBlocks[std::log2(size)].end()) {
                freeBlocks[std::log2(size)].push_back(block);
                break;
            }
            freeBlocks[std::log2(size)].erase(it);
            block &= ~size;
            size <<= 1;
        }
    }

private:
    int maxSize;
    int minBlockSize = 1;
    std::vector<std::vector<int>> freeBlocks;
};

int main() {
    BuddyAllocator allocator(1024);
    void* ptr1 = allocator.allocate(100);
    void* ptr2 = allocator.allocate(200);
    allocator.deallocate(ptr1);
    void* ptr3 = allocator.allocate(50);
    return 0;
}

3 总结

通过了解不同的内存分配算法,我们可以更好地优化程序的内存使用,提高系统的性能和稳定性。希望这篇文章不仅能为你带来技术上的提升,还能激发你对内存管理的兴趣和热情。

在实际项目中,你使用过哪些内存分配算法?它们在你的项目中表现如何?欢迎在评论区分享你的经验和见解,与其他读者互动,共同探讨内存管理的最佳实践。

References

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

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

相关文章

PlantSimulation导入cad图作为背景

PlantSimulation导入cad图作为背景 首先要整理cad文件&#xff0c;正常的工艺规划总图中存在较多杂乱文件&#xff0c;这些信息是不需要的&#xff0c;如果直接导入&#xff0c;会非常卡。 1、打开cad软件&#xff0c;使用layon命令打开所有的隐藏图层&#xff0c;删除不需要…

品品香·山东航空老白茶文化主题专属航班香上云端

&#xff16;月&#xff16;日&#xff0c;品品香山东航空“浓情过端午&#xff0c;白茶品品香”老白茶文化主题专属航班&#xff33;&#xff23;&#xff18;&#xff18;&#xff11;&#xff19;济南遥墙&#xff0d;成都天府顺利起飞&#xff0c;携中国老白茶标杆——晒白…

Spring Boot整合Redis实现发布/订阅功能

&#x1f604; 19年之后由于某些原因断更了三年&#xff0c;23年重新扬帆起航&#xff0c;推出更多优质博文&#xff0c;希望大家多多支持&#xff5e; &#x1f337; 古之立大事者&#xff0c;不惟有超世之才&#xff0c;亦必有坚忍不拔之志 &#x1f390; 个人CSND主页——Mi…

目标检测算法YOLOv9简介

YOLOv9由Chien-Yao Wang等人于2024年提出&#xff0c;论文名为&#xff1a;《YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information》&#xff0c;论文见&#xff1a;https://arxiv.org/pdf/2402.13616 &#xff1b;源码见: https://github.com/W…

U-Mail:企业邮箱系统安全解决方案

在数字化浪潮的推动下&#xff0c;互联网技术正日新月异&#xff0c;企业的信息通信需求亦随之升华。作为企业沟通的重要媒介&#xff0c;企业邮箱已被广泛应用&#xff0c;然而随着其应用范围的不断扩展&#xff0c;也给企业带来了一系列挑战&#xff1a; 一、统一身份认证管…

MySQL-数据处理函数

026-distinct去重 select job from emp;加个 distinct 就行了 select distinct job from emp;注意&#xff1a;这个去重只是将显示的结果去重&#xff0c;原表数据不会被更改。 select 永远不会改变原数据 select distinct deptno, job from emp order by deptno asc;027-数…

Kubernetes入门-大简介

目录 何为微服务 何为云原生 何为编排器 “Kubernetes”这个名字来自希腊语&#xff0c;意思是“舵手”舵手是一个航海/航行术语&#xff0c;指掌舵的人从本质上说&#xff0c;Kubernetes是云原生微服务(cloud-native microservice)应用的编排器(orchestrator) 何为微服务 …

【C++类和对象中篇】(构造函数和析构函数)

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;C课程学习 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f369;1.默认成员函数的概念&#xff1a; &#x1f369;2.构造函数&#xff1a; 2.1特性&…

刚刚❗️德勤2025校招暑期实习测评笔试SHL测评题库已发(答案)

&#x1f4e3;德勤 2024暑期实习测评已发&#xff0c;正在申请的小伙伴看过来哦&#x1f440; ㊙️本次暑期实习优先考虑2025年本科及以上学历的毕业生&#xff0c;此次只有“审计及鉴定”“税务与商务咨询”两个部门开放了岗位~ ⚠️测评注意事项&#xff1a; &#x1f44…

字节面试:CPU100% 如何处理?

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的线上问题的场景题&#xff1a; 1.CPU100%&#xff0c;你是怎么处理的&…

写给大数据开发的,要给领导汇报什么?

上篇&#xff1a;写给大数据开发&#xff0c;如何去掌握数据分析 就像说经济学家不炒股一样&#xff0c;有些数据开发不喜欢讲数据&#x1f4ca;&#xff0c;就很离谱…自己不讲数据&#xff0c;不相信数据&#xff0c;别人也不敢用了&#xff5e; 所以找上级汇报&#xff0…

【上海大学计算机组成原理实验报告】七、程序转移机制

一、实验目的 学习实现程序转移的硬件机制。 掌握堆栈寄存器的使用。 二、实验原理 根据实验指导书的相关内容&#xff0c;实验箱系统的程序转移硬件机制在于&#xff0c;当LDPC有效时&#xff0c;如果此时DUBS上的值就是转移的目标地址&#xff0c;则此目标地址被打入PC&am…

LabVIEW电池测试系统

1. 背景 随着电动汽车、可再生能源等领域的迅速发展&#xff0c;电池作为能源储存和释放的核心组件&#xff0c;其性能评估变得尤为重要。电池的充放电性能、容量、循环寿命等参数直接影响着设备的工作性能和使用寿命。因此&#xff0c;设计一套全面、准确的电池测试系统对于提…

王学岗鸿蒙开发(北向)——————(十)子组件修改父组件的内容与 动画

子组件修改父组件的内容 使用类似Android的回调&#xff0c;父组件传递给子组件一个函数 import { MyComment } from ./component/MyComment import { MyContent } from ./component/MyComtent import { MyTitleComponent } from ./component/MyTitleComponentEntry Componen…

安卓逆向经典案例——XX牛

安卓逆向经典案例——XX牛 按钮绑定方式 1.抓包 2.查看界面元素&#xff0c;找到控件id 通过抓包&#xff0c;发现点击登录后&#xff0c;才会出现Encrpt加密信息&#xff0c;所以我们通过控件找到对应id&#xff1a;btn_login 按钮绑定方法——第四种 public class LoginA…

把文件从一台linux机器上传到另一台linux机器上

文章目录 1&#xff0c;第一种情况1.1 先测试2台机器是否可以互相通信1.2 对整个文件夹里面的所有内容进行传输的命令1.3 检查结果 2&#xff0c;第二种情况2.1&#xff0c;单个文件传输的命令 1&#xff0c;第一种情况 我这里有2台linux机器&#xff0c; 机器A&#xff1a;19…

uni-app uni-swipe-action 滑动操作状态恢复

按照uni-app官方文档的写法 当前同一条滑动确认之后 页面列表刷新 但是滑动的状态还在 入下图所示&#xff1a; 我们需要在滑动确认之后 页面刷新 滑动状态恢复 那么我们就来写一下这部分的逻辑&#xff1a; 首先&#xff0c;配置一下:show"isOpened[item.id]" chan…

基于JSP的医院远程诊断系统

开头语&#xff1a; 你好呀&#xff0c;我是计算机学长猫哥&#xff01;如果有相关需求&#xff0c;文末可以找到我的联系方式。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; JSP Servlet JSPBean 工具&#xff1a; IDEA/Eclipse、Navica…

ChatTTS - 用于对话场景的文本转语音

大家好&#xff0c;我是小麦&#xff0c;今天给大家分享一款免费&#xff0c;可用于对话场景的文本转语音工具。 阅读感悟 不知道大家在日常的学习、工作中是否有这样的一个情况&#xff0c;当我们阅读完一篇文章&#xff0c;很快就能读完&#xff0c;但印象不会很深&#xf…

Python学习打卡:day01

day1 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 1、Python 软件&#xff08;PyCharm&#xff09; 安装&#xff1a;在 Linux 环境下安装 Pycharm 插件&#xff1a;汉化、翻译 设置字体大小 常用快捷…