FreeRtos heap5源码分析

本文详细介绍了heap5内存管理机制,包括多个堆区的初始化过程、碎片合并方式及与heap4的区别。通过深入剖析vPortDefineHeapRegions函数,揭示了heap5如何实现内存分配和管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

===============================   博客点滴积累,部分话语和知识点来源于网络,感谢网络资源的提供者======

heap5 与heap4 比较相似,也是实现了malloc和free,同时也可以进行碎片合并。有的区别是heap5 可以有多个堆区,static void prvHeapInit( void ) 被换成void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )这个函数。结构体HeapRegion_t(portable.h)如下:

const HeapRegion_t * const pxHeapRegions   结构体如下定义(portable.h):

/* Used by heap_5.c. */
typedef struct HeapRegion
{
uint8_t *pucStartAddress;
size_t xSizeInBytes;
} HeapRegion_t;

该函数前面有一段注释大概意思是:vPortDefineHeapRegions 一定要在使用pvPortMalloc之前使用,进行初始化栈区。创建任务,信号量,互斥锁,软件定时器,事件组等都调用pvPortMalloc。所以这个需要注意。

vPortDefineHeapRegions 函数的参数是一个结构体数组,数组的地址指针,必须从小到大排序,并且以空指针和0字节结尾

void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions )
{

BlockLink_t *pxFirstFreeBlockInRegion = NULL, *pxPreviousFreeBlock;

uint8_t *pucAlignedHeap;

size_t xTotalRegionSize, xTotalHeapSize = 0;

BaseType_t xDefinedRegions = 0;

uint32_t ulAddress;

const HeapRegion_t *pxHeapRegion;

/* Can only call once! */

configASSERT( pxEnd == NULL );

//取数组的第一个元素

pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
while( pxHeapRegion->xSizeInBytes > 0 )
{//xSizeInBytes 以 0 字节结尾
xTotalRegionSize = pxHeapRegion->xSizeInBytes;
/* Ensure the heap region starts on a correctly aligned boundary. */
ulAddress = ( uint32_t ) pxHeapRegion->pucStartAddress;
if( ( ulAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
{
ulAddress += ( portBYTE_ALIGNMENT - 1 );
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
/* 调整字节对齐 */
xTotalRegionSize -= ulAddress - ( uint32_t ) pxHeapRegion->pucStartAddress;
}
pucAlignedHeap = ( uint8_t * ) ulAddress;
/* Set xStart if it has not already been set. */
if( xDefinedRegions == 0 )

{//当是数据的第一个元素,是初始化链表的头指针,注意xStart是个结构体,结构体的pxNextFreeBlock 指针指向了pucAlignedHeap,即堆区的基地址,基地址存了什么呢?pxFirstFreeBlockInRegion 结构体,定义了heap的大小,以及下一个heap的地址


xStart.pxNextFreeBlock = ( BlockLink_t * ) pucAlignedHeap;
xStart.xBlockSize = ( size_t ) 0;
}
else
{
configASSERT( pxEnd != NULL );
configASSERT( ulAddress > ( uint32_t ) pxEnd );
}
pxPreviousFreeBlock = pxEnd;//pxEnd 是个指针。它存在heap地址的最后面
ulAddress = ( ( uint32_t ) pucAlignedHeap ) + xTotalRegionSize;
ulAddress -= uxHeapStructSize;
ulAddress &= ~portBYTE_ALIGNMENT_MASK;
pxEnd = ( BlockLink_t * ) ulAddress;//初始化heap最后的pxEnd 指针

pxEnd->xBlockSize = 0;

pxEnd->pxNextFreeBlock = NULL;

pxFirstFreeBlockInRegion = ( BlockLink_t * ) pucAlignedHeap;
pxFirstFreeBlockInRegion->xBlockSize = ulAddress - ( uint32_t ) pxFirstFreeBlockInRegion;
pxFirstFreeBlockInRegion->pxNextFreeBlock = pxEnd;
if( pxPreviousFreeBlock != NULL )
{//不是第一块,就插入链表
pxPreviousFreeBlock->pxNextFreeBlock = pxFirstFreeBlockInRegion;
}
xTotalHeapSize += pxFirstFreeBlockInRegion->xBlockSize;//统计heap大小
/* 数组下标加1,获取下一个元素 */
xDefinedRegions++;
pxHeapRegion = &( pxHeapRegions[ xDefinedRegions ] );
}
xMinimumEverFreeBytesRemaining = xTotalHeapSize;
xFreeBytesRemaining = xTotalHeapSize;
/* Check something was actually defined before it is accessed. */
configASSERT( xTotalHeapSize );
/* xBlockAllocatedBit 标记最高bit位,表示地址是否空闲 */

xBlockAllocatedBit = ( ( size_t ) 1 ) << ( ( sizeof( size_t ) * heapBITS_PER_BYTE ) - 1 );

}

Freertos是一个轻量级、实时嵌入式操作系统内核,主要用于物联网(IoT)设备和微控制器(MCU)上。它的源码解读通常涉及以下几个方面: 1. **任务管理**:Freertos的核心是任务调度机制,包括任务创建、调度、阻塞和唤醒等功能。理解`task.h`和`scheduler.c`等文件对于理解任务管理和同步至关重要。 2. **事件队列**:用于传递消息和数据,如`queue.h`里的`xQueue`函数,它们支持生产者-消费者模型,了解这些队列的实现有助于编写异步通信程序。 3. **互斥锁和信号量**:用于保护共享资源,`Semaphore.h`中的`semphores`是关键部分,确保了并发访问的同步控制。 4. **中断处理**:通过`interrupt.h`和相关驱动,理解和分析中断向量表设置以及中断服务函数的实现。 5. **内存管理**:查看`heap_1.c`和`heap_2.c`等,理解FreeRTOS如何动态分配内存给任务栈和堆。 6. **设备驱动**:虽然Freertos本身不是完整的OS,但它提供了驱动框架,例如`device Drivers`目录下的示例,可以学习如何添加对硬件的支持。 7. **API设计**:研究源码中的API接口,理解其接口结构、错误处理和性能优化策略。 要开始解读,建议先从官方文档入手,然后逐步深入源码中各个模块,同时结合实际项目练习,以提高理解和应用能力。如果你在解读过程中遇到具体的代码段或概念不明白,可以提出相关的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值