在介绍本文之前,向大家推荐个非常容易入门的人工智能学习网站,建议点击收藏❤️

目录:

  • 概述
  • heap_1.c
  • heap_2.c
    • prvHeapInit
    • pvPortMalloc
    • vPortFree
    • xPortGetFreeHeapSize
  • heap_3.c
  • heap_4.c
  • heap_5.c
  • 总结
    • 您对FreeRTOS的内存管理有比较好的理解或应用场景吗,欢迎评论区留言

概述

内存管理对应用程序和操作系统来说都非常重要。现在很多的程序漏洞和运行崩溃都和内存分配使用错误有关。FreeRTOS官方提供了5种内存管理解决方案,这里的内存一般情况下指的是RAM,主要是针对使用者可以针对不同的应用场景使用一种或同时使用多种。在同时使用多种内存管理方案时,可以将原生的API重命名,然后分别初始化,初始化的时候注意要链接不同的内存块。学习RTOS内存管理的时候要先搞清楚它的字节对齐是怎么实现的,这会对看源码有很大帮助。

heap_1.c

在系统中定义个大数组,内存管理实际就是在这个数组里面操作。这种内存管理方案不会对已申请的内存进行释放。

如上图vPortFree()里面是空操作,这种内存管理方案不对已申请的内存做释放。vPortInitialiseBlocks()是初始化,只对一个剩余内存变量置零,xPortGetFreeHeapSize()是获取剩余内存。下面通过代码注释的形式分析pvPortMalloc()。

void *pvPortMalloc(size_t xWantedSize)
{//xWantedSize:需要从大数组中获取的内存大小void *pvReturn = NULL;static uint8_t *pucAlignedHeap = NULL;/* 确保字节对齐,可以提高CPU访问速度 */
#if (portBYTE_ALIGNMENT != 1){if (xWantedSize & portBYTE_ALIGNMENT_MASK){/* Byte alignment required. */xWantedSize += (portBYTE_ALIGNMENT - (xWantedSize & portBYTE_ALIGNMENT_MASK));}}
#endifvTaskSuspendAll();{if (pucAlignedHeap == NULL){/* 确保大数组的起始地址的是对齐的,有些是2字节对齐或4字节或8字节或其他,视不同的编译器而定. */pucAlignedHeap = (uint8_t *)(((portPOINTER_SIZE_TYPE)&ucHeap[portBYTE_ALIGNMENT]) & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));}/* 检查是否有足够的空间 */if (((xNextFreeByte + xWantedSize) < configADJUSTED_HEAP_SIZE) &&((xNextFreeByte + xWantedSize) > xNextFreeByte)) /* Check for overflow. */{/* 申请成功后返回申请到的内存起始地址,以及对剩余内存变量做修改. */pvReturn = pucAlignedHeap + xNextFreeByte;xNextFreeByte += xWantedSize;}traceMALLOC(pvReturn, xWantedSize);}(void)xTaskResumeAll();#if (configUSE_MALLOC_FAILED_HOOK == 1){if (pvReturn == NULL){//内存申请失败回调函数extern void vApplicationMallocFailedHook(void);vApplicationMallocFailedHook();}}
#endifreturn pvReturn;
}

heap_2.c

这种内存管理方案在heap_1的基础上新增了内存释放的功能,通过链表来现的。

prvHeapInit

  • 内存块初始化
  • 空闲内存列表管理相关初始化话,用于内存释放。申请的次数多了会产生内存碎片。
static void prvHeapInit(void)
{BlockLink_t *pxFirstFreeBlock;uint8_t *pucAlignedHeap;/* Ensure the heap starts on a correctly aligned boundary. */pucAlignedHeap = (uint8_t *)(((portPOINTER_SIZE_TYPE)&ucHeap[portBYTE_ALIGNMENT]) & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));/* xStart is used to hold a pointer to the first item in the list of freeblocks.  The void cast is used to prevent compiler warnings. */xStart.pxNextFreeBlock = (void *)pucAlignedHeap;xStart.xBlockSize = (size_t)0;/* xEnd is used to mark the end of the list of free blocks. */xEnd.xBlockSize = configADJUSTED_HEAP_SIZE;xEnd.pxNextFreeBlock = NULL;/* To start with there is a single free block that is sized to take up theentire heap space. */pxFirstFreeBlock = (void *)pucAlignedHeap;pxFirstFreeBlock->xBlockSize = configADJUSTED_HEAP_SIZE;pxFirstFreeBlock->pxNextFreeBlock = &xEnd;
}

pvPortMalloc

void *pvPortMalloc(size_t xWantedSize)
{//如果是第一次使用本接口要先对该内存管理方案进行初始化//每次申请内存的大小需要加上链表节点大小//空闲内存管理链表的大块内存可能变成小内存//返回可使用的内存的起始地址
}

vPortFree

传入的参数往前退一个链表节点大小才能获取到每个节点的信息。

void vPortFree(void *pv)
{uint8_t *puc = (uint8_t *)pv;BlockLink_t *pxLink;if (pv != NULL){/* The memory being freed will have an BlockLink_t structure immediatelybefore it. */puc -= heapSTRUCT_SIZE;/* This unexpected casting is to keep some compilers from issuingbyte alignment warnings. */pxLink = (void *)puc;vTaskSuspendAll();{/* Add this block to the list of free blocks. */prvInsertBlockIntoFreeList(((BlockLink_t *)pxLink));xFreeBytesRemaining += pxLink->xBlockSize;traceFREE(pv, pxLink->xBlockSize);}(void)xTaskResumeAll();}
}

xPortGetFreeHeapSize

获取剩余内存大小。

heap_3.c

这种内存管理方案仅仅是对系统的malloc和free进行封装,做了线程保护。不行要自己分配大数组。

heap_4.c

该内存管理算法不会产生内存碎片,在内存回收的时候增加了附近的小内存合并的操作。
内存回收的时候,是按地址大小去遍历的:

pxPreviousBlock = &xStart;
pxBlock = xStart.pxNextFreeBlock;
while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) )
{pxPreviousBlock = pxBlock;pxBlock = pxBlock->pxNextFreeBlock;
}

需要对变量"xBlockAllocatedBit"作特别说明,它的存在使得链表节点头中的xBlockSize包含两种意思,一个是当前内存块的大小,另一个是最高位表示该内存块是否在使用中。

heap_5.c

该内存管理算法在heap_4.c的基础上增加了非连续的多个内存块的使用,体现在初始化上面:

typedef struct HeapRegion
{uint8_t *pucStartAddress;size_t xSizeInBytes;
} HeapRegion_t;HeapRegion_t xHeapRegions[] ={{(uint8_t *)0x80000000UL, 0x10000}, // << Defines a block of 0x10000 bytes starting at address 0x80000000{(uint8_t *)0x90000000UL, 0xa0000}, // << Defines a block of 0xa0000 bytes starting at address of 0x90000000{NULL, 0}                            // Terminates the array.
};vPortDefineHeapRegions(xHeapRegions);

总结

FreeRTOS将内核语内存管理分开实现,内核只规定了必要的内存管理函数原型,但不关心这些内存管理函数是如何实现的。这样的方案大大提高了系统的灵活性:不同的应用场景使用不同的内存管理算法。比如对于安全型的嵌入式系统,一般不允许动态内存分配,大都是通过静态分配的。在满足需要的前提下,系统越简单,做得越安全。

您对FreeRTOS的内存管理有比较好的理解或应用场景吗,欢迎评论区留言

【FreeRTOS】内存管理相关推荐

  1. 41 freertos内存管理试验 1

    四十一.freertos内存管理试验 1 /** *************************************************************************** ...

  2. FreeRTOS内存管理

    堆空间是一个数组,configTOTAL_HEAP_SIZE表示堆空间大小,在FreeRTOSConfig.h中宏定义 /* 由应用程序创建堆区,大小为configTOTAL_HEAP_SIZE */ ...

  3. FreeRTOS高级篇7---FreeRTOS内存管理分析

    内存管理对应用程序和操作系统来说都非常重要.现在很多的程序漏洞和运行崩溃都和内存分配使用错误有关.         FreeRTOS操作系统将内核与内存管理分开实现,操作系统内核仅规定了必要的内存管理 ...

  4. FreeRTOS:内存管理

    在FreeRTOS中有两种内存使用方法:一种是使用静态方法创建任务的栈空间.任务控制块等,该方法也就是在我们编程时候直接定义/申请一个数组或结构体内存空间:另一种是使用动态方法创建,该方法是在代码运行 ...

  5. FreeRTOS 之五 动态内存管理(heap_1.c)详解

    写在前面   写这篇文章时,网上已经有了铺天盖地的文章来介绍 FreeRTOS 的动态内存.之所以还去写这篇博文,主要还是记录自己的学习过程.结合源代码一步一步分析一下FreeRTOS究竟是怎么实现的 ...

  6. 11.FreeRTOS学习笔记-内存管理

    几种内存分配算法的比较 heap_1.c 管理方案是 FreeRTOS 提供所有内存管理方案中最简单的一个,它只能申请内存而不能进行内存释放,并且申请内存的时间是一个常量 heap_2.c方案支持释放 ...

  7. FreeRTOS源码分析与应用开发10:内存管理

    目录 1. 概述 1.1 RTOS中内存分配特点 1.2 内存堆(heap space)来源 1.2.1 ucHeap数组 1.2.2 链接器设置的堆 1.2.3 多个非连续内存堆 1.3 关于字节对 ...

  8. FreeRTOS的内存管理

    FreeRTOS的内存管理 浅析FreeRTOS_v4.5.0内存分配与回收及其改进方案 转载于:https://www.cnblogs.com/LittleTiger/p/4911633.html

  9. 韦东山freeRTOS系列教程之【第二章】内存管理

    文章目录 教程目录 2.1 为什么要自己实现内存管理 2.2 FreeRTOS的5种内存管理方法 2.2.1 Heap_1 2.2.2 Heap_2 2.2.3 Heap_3 2.2.4 Heap_4 ...

  10. FreeRTOS(基于STM32)——内存管理

    目录 内存管理的简介: 内存碎片: 五种内存的分配方法: heap_1内存分配方法: heap_2内存分配方法: heap_3内存分配方法: heap_4内存分配方法: heap_5内存分配方法: 内 ...

最新文章

  1. 你想要的宏基因组-微生物组知识全在这(180601)
  2. jstl 获取 javascript 定义的变量_一个后端开发者前端语言基础:JavaScript
  3. css BEM书写规范
  4. 51nod-1640--天气晴朗的魔法(简单最小生成树)
  5. C语言高级编程:i++与++i区别
  6. 在JDT中使用Java 8 Lambda
  7. 小白转前端,学习哪些知识点才能不走弯路?
  8. Nginx服务器防止被压力测试
  9. 蒜头君任务系统C语言,白菜君的三角形 T3180 计蒜客
  10. IBM DB2各版本下载地址
  11. 戴尔T630安装Ubuntu操作系统及Gaussian 09
  12. 基于chrome内核的微软Edge浏览器~
  13. linux安装eclipse教程,Linux下的Eclipse安装
  14. Java面试之多线程:Java创建多线程为什么只有一种方式?
  15. PDPS软件:机器人固定点焊虚拟仿真操作方法
  16. latex表格 在线生成
  17. slf4j log4j logback关系详解和相关用法 【by Sinte-Beuve】
  18. 我来到博客大世界啦!
  19. 怎么利用jquery.form 提交form
  20. 微信小程序快速开发:视频指导版

热门文章

  1. TNNLS | GNN综述:A Comprehensive Survey on Graph Neural Networks
  2. 运营和推广资讯类网站
  3. java seq_Seq命令的用法
  4. fortran使用MKL函数库中的scal计算一个标量和向量的乘积
  5. SQL SERVER 使用作业自动备份及删除过往备份
  6. python 分析外汇数据_Python/Pandas如何存储外汇勾数数据进行分析
  7. 醋都之争,是谁胆敢打翻山西人的“醋坛子”?
  8. Springboot毕设项目唐韵古都长安纪念品网站z037yjava+VUE+Mybatis+Maven+Mysql+sprnig)
  9. Flink 使用之 CEP
  10. 【纸模】六角大王 Super 5.6 CHS 简体中文版 U20080725+[手册]窗口与工具的概要(PDF格式)...