FreeRTOS(五)——heap文件解析
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文件解析相关推荐
- java解析五元组_pcap文件解析,并且按照五元组分类
[实例简介] pcap文件解析,并按照五元组分包,全部用java语言实现. [实例截图] [核心代码] PcapTestZZ ├── PcapTestZ │ ├── 111.206.37.1930 ...
- AUTOSAR从入门到精通100讲(十五)-AURIX TC3xx MCAL中Link文件解析以及代码变量定位方法详解
一 TC3xx系列MCAL中TASKING Link文件解析以及代码变量定位方法 1 TASKING Link文件解析 1.1 DSRAM中的数据存放: 在AURIX™ 2G中(以TC387为例),每 ...
- Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition
Android Animation学习(五) ApiDemos解析:容器布局动画 LayoutTransition Property animation系统还提供了对ViewGroup中的View改变 ...
- MyBatis 源码分析 - 映射文件解析过程
1.简介 在上一篇文章中,我详细分析了 MyBatis 配置文件的解析过程.由于上一篇文章的篇幅比较大,加之映射文件解析过程也比较复杂的原因.所以我将映射文件解析过程的分析内容从上一篇文章中抽取出来, ...
- awx文件解析_Android so(ELF)文件解析
一.前言 so文件是啥?so文件是elf文件,elf文件后缀名是.so,所以也被chang常称之为so文件,elf文件是linux底下二进制文件,可以理解为windows下的PE文件,在Android ...
- .so是什么文件_安卓 so 文件解析详解
so 文件是啥?so 文件是 elf 文件,elf 文件后缀名是.so,所以也被称之为so 文件, elf 文件是 linux 底下二进制文件,可以理解为 windows 下的PE文件,在 Andro ...
- 第五章 PX4-Pixhawk-GPS解析
第五章 PX4-GPS解析 在上一章节我们对传感器MPU6000做了一个解析,MPU6000所支持的协议是SPI.这一章节我们来解析GPS,GPS使用的是串口通信.这里我们着重讲解UBLOX的解析过程 ...
- 第五章 PX4-GPS解析
版权声明:本文为博主原创文章,未经博主允许不得转载. 第五章 PX4-GPS解析 在上一章节我们对传感器MPU6000做了一个解析,MPU6000所支持的协议是SPI.这一章节我们来解析GPS,GPS ...
- 基于Java的NetCDF文件解析
近期在做的项目中,需要使用Java语言进行NetCDF文件的解析. 然而,当在寻找资料时,发现基于Java语言的资料相较于Python少了很多,而且现有的基于Java解析NetCDF文件到CSV的资料 ...
最新文章
- http://www.csdn.net/
- 解决idea中连接MySQL数据库后写SQL语句没有提示
- C# webBrowser与javascript互调
- java逆数组如何print_Java 逆数组
- flash activex java_Adobe flash player ActiveX和NPAPI和PPAPI 这三个软件有什么区别?
- ASP.NET教程5
- 前端笔记-使用vue-cli(脚手架)开发TodoList
- 你们的苹果手机,关闭哪些功能比较省电?
- 图像处理中各种边缘检测的微分算子简单比较(Sobel,Robert, Prewitt,Laplacian,Canny)
- 分库分表工具:Apache ShardingSphere 5.0.0-alpha 发布
- Git项目下载部分文件或文件夹
- 随笔:读书笔记--《九败一胜:美团创始人王兴创业十年》
- 流量治理神器-Sentinel限流熔断应用实战
- 电脑windows系统动态壁纸装X器wallpaper engine下载资源和使用教程
- [安装 ADB 驱动]-手动安装 ADB 驱动得以进入 Android 手机系统
- win7驱动程序未经签名可以使用吗_win7系统驱动强制数字签名的问题
- 微表情识别的图片预处理(python版)
- php ajax jquery瀑布流,jQuery瀑布流插件——jQuery.Waterfall
- IPSec之IKEv2详解
- android 3dtouch插件,标注点支持3DTouch效果
热门文章
- LeetCode 58. Length of Last Word
- 微型计算机基础知识,微型计算机的基础知识
- 组装电脑多少钱一台_客户花9000元组装一台电脑,奸商赚5000块,利润真吓人
- Redis 和Memcache的区别
- MySQL text类型的最大长度
- Perl中删除或替换字符串中特殊字符(如空格)的方法
- Go 语言接口详解(一)
- 进程和线程的联系和区别
- 在linux系统下挂接(mount)光盘镜像文件、移动硬盘、U盘以及Windows网络共享和UNIX...
- 红包随机算法微信群红包随机算法