FreeRTOS入门——内存管理

一、堆和栈

堆(heap):就是一块空闲的内存

        malloc:从堆里划出一块空间给程序使用

        free:使用完,将这块内存空间标记为“空闲”,可以再次使用

栈(stack):函数调用的局部变量保存在栈中,当前程序的环境也保存在栈中

        可以从堆中分配一块内存空间用作栈

二、内存管理方法

FreeRTOS内存管理接口函数为:pvPortMalloc、vPortFree,对应malloc、free

源码中默认提供5个文件,对应内存管理的五种方法

1.heap_1

只有pvPortMalloc,没有vPortFree,首先定义一个大数组,在pvPortMalloc时,从这个数组中分配空间。FreeRTOS在创建任务时,需要2个内核对象:task control block(TCB)和stack,使用heap_1时分配过程如下:

A:创建任务之前,整个数组为空闲状态

B:创建任务1,蓝色区域被划分

C:创建3个任务后数组的分配情况

2.heap_2

支持pvPortMalloc和vPortFree,使用最佳匹配算法(best fit)分配内存,碎片化严重

最佳匹配算法:假设heap有3块空闲内存:5字节、25字节、100字节,pvPortMalloc想申请20字节,会找出最小且能满足pvPortMalloc的内存:25字节,将其划分为20字节和5字节,其余5字节仍然是空闲状态可以使用。分配过程如下:

A:创建了3个任务

B:删除了一个任务,空闲内存包括顶部空间、被删除的TCB空间和被删除的Stack空间

C:创建了一个新任务,与被删除任务空间相同,刚好分配至原内存3

3.heap_3

heap_3使用标准C库中的malloc、free函数,所有堆大小由链接器的配置决定,配置项configTOTAL_HEAP_SIZE不起作用。

C库中的malloc、free函数并非线程安全的,heap_3会先暂停FreeRTOS的调度器,再去调用函数,实现线程安全

4.heap_4

heap_4也是使用大数组来分配内存,通过首次适应算法来分配内存,还会将相邻空闲内存合并为一个更大的空闲内存,有助于减少内存碎片的问题。

首次适应算法(first fit):假设有三块空闲内存:5字节、200字节、100字节,pvPortMalloc想申请20字节,首先找出第一个能满足pvPortMalloc的内存:200字节,将其划分为20字节和180字节,返回20字节的地址,其余180字节仍然为空闲状态。分配过程如下:

A:创建了3个任务

B:删除了一个任务,空闲Stack和TCB被合并,空闲内存包括顶层和任务两块内存

C:分配了一个Queue,从第一个空闲块中分配部分空间

D:分配了一个User数据,从Queue后面的空闲块中分配

E:释放Queue,User前后都包含一款空闲内存

F:释放User数据,中间的空闲内存合并为一个更大的空闲内存

 5.heap_5

heap_5与heap_4内存分配、释放的算法一致,相比于heap_4,heap_5并不局限于管理一个大型数组,它可以管理多块、分隔开的内存。

内存地址不连续可以使用heap_5,在使用前需要确定这些内存块在哪、多大:

        在使用pvPortMalloc 之前,必须先指定内存块的信息 

        使用vPortDefineHeapRegions 来指定这些信息

如何指定一块内存,使用如下结构体:

typedef struct HeapRegion 
{ 
    uint8_t * pucStartAddress; // 起始地址 
    size_t xSizeInBytes;       // 大小 
} HeapRegion_t; 

如何指定多块内存,使用HeapRegion_t数组,在这个数组中,低地址在前、高地址在后:

HeapRegion_t xHeapRegions[] = 
{ 
    { ( uint8_t * ) 0x80000000UL, 0x10000 }, // 起始地址 0x80000000,大小 0x10000 
    { ( uint8_t * ) 0x90000000UL, 0xa0000 }, // 起始地址 0x90000000,大小 0xa0000 
    { NULL, 0 } // 表示数组结束 
};

把xHeapRegions 数组传给vPortDefineHeapRegions 函数,即可初始化Heap_5。vPortDefineHeapRegions 函数原型如下:

void vPortDefineHeapRegions( const HeapRegion_t * const pxHeapRegions ); 

三、Heap相关函数

1.pvPortMalloc/vPortFree

作用:分配内存、释放内存

分配不成功返回值为NULL

void * pvPortMalloc( size_t xWantedSize ); 
void vPortFree( void * pv );

2.xPortGetFreeHeapSize

作用::当前还有多少空闲内存,Heap_3中无法使用

可以用来优化内存的使用情况,当所有内核对象都分配好,执行此函数发现返回2000,说明还有2000空闲内存,那么configTOTAL_HEAP_SIZE 就可减小2000。

size_t xPortGetFreeHeapSize( void );

3.xPortGetMinimumEverFreeHeapSize

作用:程序运行过程中,返回空闲内存容量的最小值,仅heap_4、heap_5支持

size_t xPortGetMinimumEverFreeHeapSize( void ); 

4.malloc 失败的钩子函数

在pvPortMallc函数内部,pvPortMallc失败时会调用此函数

使用时需要在FreeRTOSConfig.h 中,把configUSE_MALLOC_FAILED_HOOK 定义为1,并提供vApplicationMallocFailedHook 函数

void * pvPortMalloc( size_t xWantedSize )vPortDefineHeapRegions 
{ 
    ...... 
    #if ( configUSE_MALLOC_FAILED_HOOK == 1 ) 
    { 
        if( pvReturn == NULL ) 
        { 
        extern void vApplicationMallocFailedHook( void ); 
        vApplicationMallocFailedHook(); 
        } 
    } 
    #endif 
    return pvReturn;         
} 

FreeRTOS内存管理方法4是通过增加一个内存合并算法来提高内存使用效率。这种方法与前文介绍的第二种方法相似,使用一个大数组来管理内存,定义为`static uint8_t ucHeap\[configTOTAL_HEAP_SIZE\]`。在这种方法中,有三个关键函数用于内存分配和释放。首先是`pvPortMalloc`函数,用于分配内存空间。它接受一个参数`xWantedSize`,表示需要分配的内存大小。然后是`vPortFree`函数,用于释放内存空间。它接受一个参数`pv`,表示要释放的内存指针。最后是`prvInsertBlockIntoFreeList`函数,用于将相邻的小的空闲内存块合并成一个大块,以避免内存泄露。释放内存的具体实现如下所示: ```c void vPortFree(void *pv) { if (pv) { vTaskSuspendAll(); { free(pv); traceFREE(pv, 0); } (void)xTaskResumeAll(); } } ``` 这个函数首先检查传入的内存指针是否为空,然后使用`free`函数释放内存,并调用`traceFREE`函数进行内存追踪。最后,使用`vTaskSuspendAll`和`xTaskResumeAll`函数来保证在释放内存的过程中不会发生任务切换。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [基于freertos的嵌入式系统开发(六)FreeRTOS内存管理方法4](https://blog.csdn.net/cyjbj/article/details/127031092)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [FreeRTOS --(4)内存管理 heap3](https://blog.csdn.net/zhoutaopower/article/details/106677144)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值