FreeRtos内存管理
标签(空格分隔): FreeRtos内存
FreeRtos的内存管理接口,都遵循POSIX接口标准.可移植操作系统接口(英语:Portable Operating System Interface,缩写为POSIX),是IEEE为要在各种UNIX操作系统上运行软件,而定义API的一系列互相关联的标准的总称,其正式称呼为IEEE Std 1003,而国际标准名称为ISO/IEC 9945。该标准要求malloc分配的内存地址必须是对齐的地址.
FreeRtos 内存管理共4种方式,分别对应源码文件中的heap_1.c,heap_2.c,heap_3.c,heap_4.c.
FreeRtos内存管理方式 | 优点 | 缺点 | 备注 |
---|---|---|---|
heap_1.c | 只能malloc,不能free | ||
heap_2.c | 1.malloc速度快 |
1.容易出现内存碎片,如果不停的malloc小内存块,大内存块会被拆分为小的内存块,但是free的时候,并不会将小内存块合并,就会出现malloc大内存,无法分配成功的问题 2.free时,无法对该节点检查.free其他内存,或者free两次,无法检查 |
Free-list链表的节点是按照节点内存块大小排序的 |
heap_3.c | 采用系统默认的malloc和free,只是添加了线程保护 | ||
heap_4.c | 1.内存合并功能,不会出现内存碎片 2.添加节点保护,malloc时会在内存快上设定标志位,避免多次free和free其他内存引起的crash |
1.malloc的时候有大小限制,因为malloc标志位是放在size的最高bit 2.malloc的时间比heap_2.c要慢 |
Free-list链表的节点是按照节点地址排序的,目的是方便内存合并 |
1 heap_1.c源码分析
这种方式比较简单,只支持用户malloc内存,不支持用户free.heap_1的内存池是用户自定义了一块数组,为了保证地址对齐,将该数组放在了结构体的第2个元素.
#全局数组ucHeap作为heap的内存词,这里为了保证heap起始地址是4字节对齐的,将ucHeap放在结构体里面保证地址对齐.
extern struct xRTOS_HEAP
{
unsigned long ulDummy;
unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];
} xHeap;
void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn = 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. */
#保证malloc的长度是4字节对齐的,那下一次malloc的地址还是4字节对齐的
xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
}
#endif
vTaskSuspendAll();
{
/* Check there is enough room left for the allocation. */
if( ( ( xNextFreeByte + xWantedSize ) < configTOTAL_HEAP_SIZE ) &&
( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) )/* Check for overflow. */
{
/* Return the next free byte then increment the index past this
block. */
pvReturn = &( xHeap.ucHeap[ xNextFreeByte ] );
xNextFreeByte += xWantedSize;
}
}
xTaskResumeAll();
return pvReturn;
}
2 heap_2.c源码分析
heap_2的内存池也是一块用户自定义的静态数组,与heap_1的区别是,这块数组的初始化地址可能是非4字节对齐的.因此初始化的时候会取4字节对齐的地址开始作为整个内存池使用.
heap_2的核心思想是将空闲的内存,放到Free-List链表里面管理.Free-List链表里面的节点是按照该节点内存块大小排序存储的.每次malloc的时候,会从Free-List链表里面取出来可以满足malloc大小的节点使用,同时在malloc的时候,会对较大的节点进行拆分,将空闲区域按照区域大小排序插入到Free-List的列表里面.用户调用Free的时候,也是将某个节点插入到Free-List链表里面.
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_ALIGN