FreeRTOS提供了5中内存分配的方式,分别在heap_1.c, heap_2.c, heap_3.c, heap_4.c, heap_5.c中。

对于传统的库函数malloc和free,有以下的缺陷:

  • 线程不安全
  • 耗时
  • 有些嵌入式硬件没有实现

所以FreeRTOS提供了5中内存分配的方式,用户当然也可以自己实现。

下面分别来解析以下这5个heap文件
5个heap的位置在Source/portable/MemMang/

heap_1.c

  • 从一个静态数组力分配
  • 只分配内存,不释放

适用于不会删除任务 、队列、信号量、互斥量的应用程序

注释

The simplest possible implementation of pvPortMalloc().  Note that this implementation does NOT allow allocated memory to be freed again.

表示只分配,不释放

内存分配函数

void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn = NULL;
static uint8_t *pucAlignedHeap = NULL;/* Ensure that blocks are always aligned to the required number of bytes. */#if( portBYTE_ALIGNMENT != 1 ){if( xWantedSize & portBYTE_ALIGNMENT_MASK ){/* Byte alignment required. */xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}}#endifvTaskSuspendAll();{if( pucAlignedHeap == NULL ){/* Ensure the heap starts on a correctly aligned boundary. */pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );}/* Check there is enough room left for the allocation. */if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )    )/* Check for overflow. */{/* Return the next free byte then increment the index past thisblock. */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;
}

解析

首先是内存对齐判断

    #if( portBYTE_ALIGNMENT != 1 ){if( xWantedSize & portBYTE_ALIGNMENT_MASK ){/* Byte alignment required. */xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}}#endif

这里,如果内存对齐有效,则执行,如果要分配的内存不是对齐字节(通常是8)的整数倍,则补齐,所以xWantedSize要加上要补齐的长度

然后挂起调度器

vTaskSuspendAll();

防止分配内存过程中被打断。

静态数组对齐检查

pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );

这里uheap就是静态数组,首先确保它对齐了,因为uheap的首地址可能不是8的倍数,所以,确保实际开始分配的地址是对齐的
比如基础地址低三位是3,+8之后是11,屏蔽低三位后是8,也就是8的倍数,对齐了,这样开头就有5个字节直接被抛弃了

溢出检测

if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) && ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )    )
/* Check for overflow. */

分配内存

pvReturn = pucAlignedHeap + xNextFreeByte;
xNextFreeByte += xWantedSize;

恢复调度器

( void ) xTaskResumeAll();

分配失败hook函数

    #if( configUSE_MALLOC_FAILED_HOOK == 1 ){if( pvReturn == NULL ){extern void vApplicationMallocFailedHook( void );vApplicationMallocFailedHook();}}#endif

如果开启了分配失败hook函数,就调用该hook

释放

void vPortFree( void *pv )
{/* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c andheap_4.c for alternative implementations, and the memory management pages ofhttp://www.FreeRTOS.org for more information. */( void ) pv;/* Force an assert as it is invalid to call this function. */configASSERT( pv == NULL );
}

heap_1.c里不释放内存

heap_2.c

/** A sample implementation of pvPortMalloc() and vPortFree() that permits* allocated blocks to be freed, but does not combine adjacent free blocks* into a single larger block (and so will fragment memory).  See heap_4.c for* an equivalent that does combine adjacent blocks into single larger blocks.*/

分配和释放内存,但对内存碎片不做处理,也就是说,不会把内存碎片合并为一个大的碎片

void *pvPortMalloc( size_t xWantedSize )
{
BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
static BaseType_t xHeapHasBeenInitialised = pdFALSE;
void *pvReturn = NULL;vTaskSuspendAll();{/* If this is the first call to malloc then the heap will requireinitialisation to setup the list of free blocks. */if( xHeapHasBeenInitialised == pdFALSE ){prvHeapInit();xHeapHasBeenInitialised = pdTRUE;}/* The wanted size is increased so it can contain a BlockLink_tstructure in addition to the requested amount of bytes. */if( xWantedSize > 0 ){xWantedSize += heapSTRUCT_SIZE;/* Ensure that blocks are always aligned to the required number of bytes. */if( ( xWantedSize & portBYTE_ALIGNMENT_MASK ) != 0 ){/* Byte alignment required. */xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );}}if( ( xWantedSize > 0 ) && ( xWantedSize < configADJUSTED_HEAP_SIZE ) ){/* Blocks are stored in byte order - traverse the list from the start(smallest) block until one of adequate size is found. */pxPreviousBlock = &xStart;pxBlock = xStart.pxNextFreeBlock;while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock != NULL ) ){pxPreviousBlock = pxBlock;pxBlock = pxBlock->pxNextFreeBlock;}/* If we found the end marker then a block of adequate size was not found. */if( pxBlock != &xEnd ){/* Return the memory space - jumping over the BlockLink_t structureat its start. */pvReturn = ( void * ) ( ( ( uint8_t * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );/* This block is being returned for use so must be taken out of thelist of free blocks. */pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;/* If the block is larger than required it can be split into two. */if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE ){/* This block is to be split into two.  Create a new blockfollowing the number of bytes requested. The void cast isused to prevent byte alignment warnings from the compiler. */pxNewBlockLink = ( void * ) ( ( ( uint8_t * ) pxBlock ) + xWantedSize );/* Calculate the sizes of two blocks split from the singleblock. */pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;pxBlock->xBlockSize = xWantedSize;/* Insert the new block into the list of free blocks. */prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );}xFreeBytesRemaining -= pxBlock->xBlockSize;}}traceMALLOC( pvReturn, xWantedSize );}( void ) xTaskResumeAll();#if( configUSE_MALLOC_FAILED_HOOK == 1 ){if( pvReturn == NULL ){extern void vApplicationMallocFailedHook( void );vApplicationMallocFailedHook();}}#endifreturn pvReturn;
}
/*-----------------------------------------------------------*/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();}
}
/*-----------------------------------------------------------*/

解析以下,heap_2.c里,不同内存间靠链表维系。
所以有这么一个结构体

typedef struct A_BLOCK_LINK
{struct A_BLOCK_LINK *pxNextFreeBlock;   /*<< The next free block in the list. */size_t xBlockSize;                      /*<< The size of the free block. */
} BlockLink_t;

这个结构体主要充当表头的作用,用来串起每一块内存,方便分配和释放,分配就是一个插入链表的操作,释放就是删除链表的操作。

heap_3.c

这个文件里直接调用了malloc和free,依赖平台自己的实现。

void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn;vTaskSuspendAll();{pvReturn = malloc( xWantedSize );traceMALLOC( pvReturn, xWantedSize );}( void ) xTaskResumeAll();#if( configUSE_MALLOC_FAILED_HOOK == 1 ){if( pvReturn == NULL ){extern void vApplicationMallocFailedHook( void );vApplicationMallocFailedHook();}}#endifreturn pvReturn;
}
/*-----------------------------------------------------------*/void vPortFree( void *pv )
{if( pv ){vTaskSuspendAll();{free( pv );traceFREE( pv, 0 );}( void ) xTaskResumeAll();}
}

heap_4.c

同heap_2.c的实现,不同的是,4会合并内存碎片,而且比malloc高效,非常常用,但是依然有碎片的风险。
它只是把空闲内存都串起来。
比如要分配一个大内存,但是内存里都是不连续的碎片空间,也会造成失败

heap_5.c

同4,不同的,可以使用不连续的内存空间。

参考:

http://elmagnificogi.github.i...

FreeRTOS(五)——heap文件解析相关推荐

  1. java解析五元组_pcap文件解析,并且按照五元组分类

    [实例简介] pcap文件解析,并按照五元组分包,全部用java语言实现. [实例截图] [核心代码] PcapTestZZ ├── PcapTestZ │   ├── 111.206.37.1930 ...

  2. AUTOSAR从入门到精通100讲(十五)-AURIX TC3xx MCAL中Link文件解析以及代码变量定位方法详解

    一 TC3xx系列MCAL中TASKING Link文件解析以及代码变量定位方法 1 TASKING Link文件解析 1.1 DSRAM中的数据存放: 在AURIX™ 2G中(以TC387为例),每 ...

  3. Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition

    Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...

  4. MyBatis 源码分析 - 映射文件解析过程

    1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...

  5. awx文件解析_Android so(ELF)文件解析

    一.前言 so文件是啥?so文件是elf文件,elf文件后缀名是.so,所以也被chang常称之为so文件,elf文件是linux底下二进制文件,可以理解为windows下的PE文件,在Android ...

  6. .so是什么文件_安卓 so 文件解析详解

    so 文件是啥?so 文件是 elf 文件,elf 文件后缀名是.so,所以也被称之为so 文件, elf 文件是 linux 底下二进制文件,可以理解为 windows 下的PE文件,在 Andro ...

  7. 第五章 PX4-Pixhawk-GPS解析

    第五章 PX4-GPS解析 在上一章节我们对传感器MPU6000做了一个解析,MPU6000所支持的协议是SPI.这一章节我们来解析GPS,GPS使用的是串口通信.这里我们着重讲解UBLOX的解析过程 ...

  8. 第五章 PX4-GPS解析

    版权声明:本文为博主原创文章,未经博主允许不得转载. 第五章 PX4-GPS解析 在上一章节我们对传感器MPU6000做了一个解析,MPU6000所支持的协议是SPI.这一章节我们来解析GPS,GPS ...

  9. 基于Java的NetCDF文件解析

    近期在做的项目中,需要使用Java语言进行NetCDF文件的解析. 然而,当在寻找资料时,发现基于Java语言的资料相较于Python少了很多,而且现有的基于Java解析NetCDF文件到CSV的资料 ...

最新文章

  1. http://www.csdn.net/
  2. 解决idea中连接MySQL数据库后写SQL语句没有提示
  3. C# webBrowser与javascript互调
  4. java逆数组如何print_Java 逆数组
  5. flash activex java_Adobe flash player ActiveX和NPAPI和PPAPI 这三个软件有什么区别?
  6. ASP.NET教程5
  7. 前端笔记-使用vue-cli(脚手架)开发TodoList
  8. 你们的苹果手机,关闭哪些功能比较省电?
  9. 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)
  10. 分库分表工具:Apache ShardingSphere 5.0.0-alpha 发布
  11. Git项目下载部分文件或文件夹
  12. 随笔:读书笔记--《九败一胜:美团创始人王兴创业十年》
  13. 流量治理神器-Sentinel限流熔断应用实战
  14. 电脑windows系统动态壁纸装X器wallpaper engine下载资源和使用教程
  15. [安装 ADB 驱动]-手动安装 ADB 驱动得以进入 Android 手机系统
  16. win7驱动程序未经签名可以使用吗_win7系统驱动强制数字签名的问题
  17. 微表情识别的图片预处理(python版)
  18. php ajax jquery瀑布流,jQuery瀑布流插件——jQuery.Waterfall
  19. IPSec之IKEv2详解
  20. android 3dtouch插件,标注点支持3DTouch效果

热门文章

  1. LeetCode 58. Length of Last Word
  2. 微型计算机基础知识,微型计算机的基础知识
  3. 组装电脑多少钱一台_客户花9000元组装一台电脑,奸商赚5000块,利润真吓人
  4. Redis 和Memcache的区别
  5. MySQL text类型的最大长度
  6. Perl中删除或替换字符串中特殊字符(如空格)的方法
  7. Go 语言接口详解(一)
  8. 进程和线程的联系和区别
  9. 在linux系统下挂接(mount)光盘镜像文件、移动硬盘、U盘以及Windows网络共享和UNIX...
  10. 红包随机算法微信群红包随机算法