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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django ListView 列表视图类

ListView是Django的通用视图之一&#xff0c;它用于显示一个对象列表。这个视图将所有的对象作为一个上下文变量传递给模板。 1&#xff0c;创建应用 python manage.py startapp app3 2&#xff0c;注册应用 Test/Test/settings.py Test/Test/urls.py 3&#xff0c;添加模型 …

IDEA去除代码和XML中的波浪线(黄色警告线)

通常情况下&#xff0c;IDE自带的侦测功能会帮我们提示一些错误、警告等。但这对于强迫症患者来说并不友好。以下是去除IDE代码和XML文件中的波浪线&#xff08;黄色警告线&#xff09;、拯救强迫症患者的有效方案 1、去除XML中的波浪线 2、去除代码中的波浪线 关爱强迫症患者…

Go模板页面浏览器显示HTML源码问题

<!--* Title: This is a file for ……* Author: JackieZheng* Date: 2024-06-09 17:00:01* LastEditTime: 2024-06-09 17:01:12* LastEditors: Please set LastEditors* Description:* FilePath: \\GoCode\\templates\\index.html --> <!DOCTYPE html> <html …

第一次视频学习

1、了解AI答题应用 1.1 业务流程架构图 1.2 自定义上传题目流程 1.3 时序图 这个比较困难&#xff0c;第一次了解到流式&#xff0c;便于前端与用户交互

2024年IntelliJ系列最新专业版安装码教程!(持续更新)

本教程适用于 J B 全系列产品&#xff0c;包括 Pycharm、IDEA、WebStorm、Phpstorm、Datagrip、RubyMine、CLion、AppCode 等。 2018-2024 均适用&#xff01; &#xff08;直接复制&#xff0c;拿走不谢&#xff09; 9H1390TRAK-eyJsaWNlbnNlSWQiOiI5SDEzOTBUUkFLIiwibGljZW…

Kubernetes入门-大简介

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

力扣刷题--728. 自除数【简单】

题目描述 自除数 是指可以被它包含的每一位数整除的数。 例如&#xff0c;128 是一个 自除数 &#xff0c;因为 128 % 1 0&#xff0c;128 % 2 0&#xff0c;128 % 8 0。 自除数 不允许包含 0 。 给定两个整数 left 和 right &#xff0c;返回一个列表&#xff0c;列表的…

安利一款非常不错浏览器文本翻译插件(效果很不错,值得一试)

官网地址&#xff1a;https://immersivetranslate.com/ “沉浸式翻译”这个词&#xff0c;由我们发明创造。如今&#xff0c;它已然成为“双语对照翻译”的代名词。自2023年上线以来&#xff0c;这款备受赞誉的 AI 双语对照网页翻译扩展&#xff0c;已帮助超过 100 万用户跨越语…

USB (3)

USB 流控 USB是polled bus,这和PCIe不一样,所有的transfer都是由host发起的。 对于IN(从device到host)。 如果device没有数据,那么只能回复NAK。 Token received corrupted

2024年高考作文考人工智能,人工智能写作文能否得高分

前言 众所周知&#xff0c;今年全国一卷考的是人工智能&#xff0c;那么&#xff0c;我们来测试一下&#xff0c;国内几家厉害的人工智能他们的作答情况&#xff0c;以及能取得多少高分呢。由于篇幅有限&#xff0c;我这里只测试一个高考真题&#xff0c;我们这里用百度的文心…

MySQL事务,视图,用户管理学习笔记【事务概念 | 事务隔离级别 | 设置级别 | 视图 | 用户管理】

博客主页&#xff1a;花果山~程序猿-CSDN博客 文章分栏&#xff1a;MySQL之旅_花果山~程序猿的博客-CSDN博客 关注我一起学习&#xff0c;一起进步&#xff0c;一起探索编程的无限可能吧&#xff01;让我们一起努力&#xff0c;一起成长&#xff01; 目录 一&#xff0c;事务初…

109.网络游戏逆向分析与漏洞攻防-装备系统数据分析-商店与捨取窗口数据的处理

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 现在的代码都是依据数据包来写的&#xff0c;如果看不懂代码&#xff0c;就说明没看懂数据包…

使用 Scapy 库编写 TCP ACK 洪水攻击脚本

一、介绍 TCP ACK洪水攻击是一种分布式拒绝服务攻击&#xff08;DDoS&#xff09;&#xff0c;攻击者通过向目标服务器发送大量伪造的TCP ACK&#xff08;确认&#xff09;数据包&#xff0c;使目标服务器不堪重负&#xff0c;无法正常处理合法请求。虽然ACK包通常用于确认接收…

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

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

【数据分析基础】实验三 文件操作、数组与矩阵运算

一&#xff0e;实验目的 掌握上下文管理语句with的使用方法。掌握文本文件的操作方法。了解os、os.path模块的使用。掌握扩展库Python-docx、openpyxl的安装与操作word、Excel文件内容的方法。熟练掌握numpy数组相关运算和简单应用。熟练使用numpy创建矩阵&#xff0c;熟悉常用…

Python | Leetcode Python题解之第135题分发糖果

题目&#xff1a; 题解&#xff1a; class Solution:def candy(self, ratings: List[int]) -> int:n len(ratings)ret 1inc, dec, pre 1, 0, 1for i in range(1, n):if ratings[i] > ratings[i - 1]:dec 0pre (1 if ratings[i] ratings[i - 1] else pre 1)ret p…

27-LINUX--I/O复用-poll

一.poll概述 poll是一个多路复用的I/O模型&#xff0c;一个进程监视多个文件描述符&#xff0c;当文件描述符就绪时&#xff0c;poll返回可读并做相应处理。 1.poll的模型 #include <poll.h>struct pollfd {int fd; //文件描述符short events; //事件类型 s…

codesys【CAN总线】

1下载设备描述文件&#xff1a; 必须下载设备描述文件&#xff0c;要不然编程软件无法正确组态。 根据实际设备【品牌】去官网搜索下载。 以 DMA882-CAN 为例 CAN的设备描述文件是【.eds】的扩展名 安装设备描述文件。 2添加CAN总线&#xff1a; 1添加【CAN总线】&#xff1a…

Chroium 源码目录结构分析(1):源码目录体积一栏

获取源码 首先&#xff0c;我们拉一份最新的源代码&#xff08;笔者是2024.6.6日拉取的&#xff09;&#xff1a; fetch --nohistory chromium 源码预处理 如果运行build&#xff0c;会生成许多生成的代码&#xff0c;因此我们不运行build。 然后&#xff0c;把干扰后续分析…

Map深度学习

Map Map是一个键值对的集合&#xff0c;和object类似&#xff0c;Map作为构造函数&#xff0c;可以通过全局对象获取到。需要通过new操作创建实例对象&#xff0c;直接调用会报错。Map构造函数接受一个iterable类型的函数&#xff0c;用来初始化Map。 var m new Map([[1, &qu…