首页 > 系统相关 >嵌入式动态内存管理实现V2

嵌入式动态内存管理实现V2

时间:2024-12-18 11:34:01浏览次数:8  
标签:动态内存 nNode uint8 嵌入式 V2 内存 heap iNode SIZE

一、说明

动态内存管理指的是在程序需要内存时申请,在使用完成后释放,保证以比较少的内存实现更多的软件需求。与之相对的是静态内存,典型的静态内存就是全局变量:在程序启动时到整个生命空间内都占用空间。动态内存的特点就是实现内存的“按需使用”,在嵌入式开发环境中,节省ram实现更多更灵活的内存使用需求。c库中的malloc、free接口就是动态内存申请、释放的实现。在《深入理解计算机系统》书中针对c库中malloc的实现算法有一章的篇幅进行说明。

V2是因为几年前写过一版动态内存管理,整体思路是:

使用链表管理已经申请的内存,申请时检查容器中未被申请的空间,在这个空间内创建节点放在链表上。内存释放时将节点中的内存释放出来并删除节点。这个管理方案中申请内存没有考虑最优方案,会产生过多的内存碎片导致空间利用率太低

代码仓库

https://gitee.com/hu_daxia/cuteheap

二、软件设计

2.1 改动项目

新版本软件同样采用一个双向链表实现,相比于之前的链表只存放已申请节点增加了未申请节点,这样在内存申请已经释放合并时更加灵活。同时在申请处理中增加了查找最优申请节点的处理,极大的减少了内存碎片增加空间利用率。

链表节点包含三个属性:用于挂在链表上的节点,是否被申请属性,大小属性

2.2 场景举例

可视化举例说明内存申请释放,使用图片的形式说明内存在申请、释放时链表的动态变化

  1. 动态内存初始化完成
  2. 申请1、2、3三个节点
  3. 释放掉上述的2号节点
  4. 申请一块比2空间大的节点
  5. 释放上述的3号节点,2号与3号合并
  6. 申请一个小于2号节点的节点

2.3 内存申请软件流程

2.4 内存释放软件流程

三、软件实现

代码仓库

申请部分:

uint8_t *heap_malloc(uint32_t wantSize)
{
    static uint8_t heapInit = 0;
    uint8_t nodeState;
    uint32_t currentSize;
    uint32_t tempSize = HEAP_SIZE - NODE_SIZE;
    HeapNode *nNode = NULL;
    Node *iNode = NULL;
    if (!heapInit)
    {
        heapInit = 1;、
        heap_init();
    }
    if (wantSize > HEAP_SIZE - NODE_SIZE)
    {
        return NULL;
    }
    for (iNode = heapList.pHead.pNext; NULL != iNode->pNext; iNode = iNode->pNext)
    {
        nodeState = ((HeapNode *)iNode)->isUsed;
        if (!nodeState)
        {
            currentSize = ((HeapNode *)iNode)->size;
            if (currentSize < wantSize)
            {
                continue;
            }
            else if (currentSize > wantSize + NODE_SIZE)
            {
                if (currentSize <= tempSize)
                {
                    tempSize = currentSize;
                    nNode = (HeapNode *)iNode;
                }
            }
            else 
            {
                nNode = (HeapNode *)iNode;
                nNode->isUsed = 1;
                return (uint8_t *)((uint8_t *)nNode + NODE_SIZE);
            }
        }
    }
    if (NULL != nNode)
    {
        HeapNode *tNode = (HeapNode *)((uint8_t *)nNode + NODE_SIZE + wantSize);
        tNode->isUsed = 0;
        tNode->size = nNode->size - wantSize - NODE_SIZE;
        list_insert((Node *)nNode,(Node *)tNode);
        nNode->size = wantSize;
        nNode->isUsed = 1;
        return (uint8_t *)((uint8_t *)nNode + NODE_SIZE);
    }
    else
    {
        return NULL;
    }
}

释放部分:

// 内存释放
void heap_free(uint8_t *ptr)
{
    if ((ptr > (uint8_t *)(gHeapSpace + HEAP_SIZE - NODE_SIZE)) ||
        (ptr < (uint8_t *)gHeapSpace))
    {
        return;
    }
    Node *iNode = heapList.pHead.pNext;
    HeapNode *nNode = NULL;
    for (; NULL != iNode->pNext; iNode = iNode->pNext)
    {
        if ((ptr - NODE_SIZE) == (uint8_t *)iNode)
        {
            nNode = (HeapNode *)iNode;
            nNode->isUsed = 0;
            break;
        }
    }
    if (nNode != NULL)
    {
        if (0 == ((HeapNode *)(iNode->pNext))->isUsed)
        {
            nNode->size = nNode->size + NODE_SIZE + ((HeapNode *)(iNode->pNext))->size;
            list_delete(iNode->pNext);
        }
        if (0 == ((HeapNode *)(iNode->pPrev))->isUsed)
        {
            HeapNode *tNode = (HeapNode *)(iNode->pPrev);
            tNode->size = tNode->size + NODE_SIZE + nNode->size;
            list_delete(iNode);
        }
    }
}

实测用例:

int main()
{
    heap_init();
    heap_foreach();
    uint8_t *p1 = heap_malloc(50);
    uint8_t *p2 = heap_malloc(20);
    uint8_t *p3 = heap_malloc(20);
    heap_foreach();
    heap_free(p2);
    heap_foreach();
    uint8_t *p4 = heap_malloc(70);
    heap_foreach();
    heap_free(p3);
    heap_foreach();
    uint8_t *p5 = heap_malloc(30);
    heap_foreach();
}

运行效果:

四、待改善

  1. 申请的和释放的时间不确定
  2. 节点本身占用空间,节点太多导致可使用空间变少

标签:动态内存,nNode,uint8,嵌入式,V2,内存,heap,iNode,SIZE
From: https://www.cnblogs.com/bliss-/p/18614423

相关文章

  • 【亲测能用】Photoshop 2025 v26.1.0正式版(ps2025下载)最新免费激活版
    软件简介说到AdobePhotoshop,我们可以有把握地说它是当今排名第一的图形软件。世界各地数以百万计的设计师、摄影师和艺术家使用Photoshop将不可能变成可能。从海报到包装,从基本的横幅到精美的网站,从令人难忘的徽标到引人注目的图标,Photoshop不断推动创意世界的发展。直观的......
  • 电脑端 TikTok视频无水印下载器 4K Tokkit v2.7.4 免费版
    4KTokkit是一款适用于PC端的TikTok下载工具,用户可以使用它轻松下载TikTok的视频、标签、用户内容以及字幕,甚至能批量下载或按日期下载新的TikTok视频。同时,它还支持备份TikTok账户数据,操作简单,但功能十分强大,帮助用户随时保存自己喜欢的TikTok内容。该版本已内置许可证,可以......
  • 动态内存管理
    一、malloc和 freemalloc函数负责向内存申请空间,free负责释放空间,它俩是一对  <stdlib.h>molloc申请size个字节大小的空间,这块空间是没有被初始化的,返回类型,如果申请成功,将申请的地址返回,如果失败,返回NULLfree用于释放先前malloc、calloc、realloc申请的空间;......
  • RT-DETR融合[ICCV2023]DySample中的上采样模块
    RT-DETR使用教程: RT-DETR使用教程RT-DETR改进汇总贴:RT-DETR更新汇总贴《DySample:LearningtoUpsamplebyLearningtoSample》一、模块介绍    论文链接: https://arxiv.org/abs/2308.15085    代码链接:https://github.com/tiny-smart/dysam......
  • 【Spring】Spring Boot快速接入Apollo V2配置中心
    文章目录1.概述2.MetaServer3.AdminService4.Portal5.开发实践1.概述本章主要介绍ApolloV2配置中心,这个涉及3个端口,4个服务。Apollo配置中心是由携程开发的配置组件,和我们的nacos差不多,不过Apollo的性能和功能上,要不Nacos要强大一些。2.MetaServer8......
  • 嵌入式从入门到入土:Linux(5)
    嵌入式从入门到入土:Linux(5)主要内容网络相关指令进程相关指令磁盘相关指令挂载与卸载Linux共享环境搭建虚拟机网络模式桥接模式和windows共享一个网段,并且能够与windows系统一样可以连接到互联网说明:虚拟机类似于一台电脑连接到了路由器好处:网络稍微会快一点坏处:占......
  • UI框架DevExpress XAF v24.2新功能预览 - .NET Core / .NET增强
    DevExpressXAF是一款强大的现代应用程序框架,允许同时开发ASP.NET和WinForms。DevExpressXAF采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。在上文中(点击这里回顾>>),我们为大家介绍了DevExpressXAFv24.2......
  • LameUI:轻量级嵌入式图形用户界面的绝佳选择
    在信息技术迅猛发展的今天,嵌入式系统逐渐成为各种智能设备的核心。这些系统往往面临资源有限的挑战,因此在开发用户界面时,使用轻量级、易于实现的库显得尤为重要。在这种背景下,LameUI应运而生。作为一个轻量级且平台无关的图形用户界面库,LameUI旨在为开发者提供简便的UI解决方......
  • ARM嵌入式学习--第七天(GPT)
    GPT-介绍  GPT有一个32位向上计数器,定时计数器值可以使用外部引脚上的事件捕获到寄存器中,捕获触发器可以被编程为上升沿和下降沿。GPT还可以在输出比较引脚上生成事件,并在定时器达到编程值时产生中断。GPT有一个12位预分频器,它提供从多个时钟源获得的可编程时钟频率 ......
  • HarmonyOS Next V2 @Event
    HarmonyOSNextV2@Event背景在上一节中,我们针对父子组件,讲了关于传递数据的知识。我们了解到@Local是管理自己内部的数据的,@Param是负责接收父组件的数据的,而且子自己内部不能直接修改按照一个组件最基本的功能,既能接收外部传入的数据,也要向外部传递数据。那么@Event......