【FreeRTOS】13 动态内存管理

本节我们来学习FreeRTOS的动态内存管理功能。

在FreeRTOS中,动态内存管理是非常重要的功能,之前讲过的任务创建、信号量创建、消息队列的创建等等,都有动态创建和静态创建两种方式。静态创建时,需要用户先定义一块内存区;而动态创建时,不需要指定内存区,系统会自动在堆(heap)中申请一块内存区;这里动态创建时,就用到了动态内存管理的功能;此外,用户的应用程序也可以动态申请内存区使用。

1)FreeRTOS动态内存管理

说到动态内存管理,我们最容易想到的就是C语言中的动态内存分配函数malloc(),这个函数可以申请一块指定大小的内存区,以指针形式返回内存的地址。用户可以使用这片内存,用完之后要用free()函数来释放,否则会造成内存泄漏。

在嵌入式系统中,为了提高代码的运行效率,一般不使用标准C的malloc和free函数,通常会用相对简单的方法去实现内存的分配,再封装成与malloc和free相同的函数接口。

FreeRTOS中,申请内存的函数原型如下:

void *pvPortMalloc( size_t xWantedSize );//参数为需申请的字节数,返回地址指针;

释放内存的函数原型如下:

void vPortFree( void *pv ); //参数为指向内存的指针;

虽然FreeRTOS提供了统一的函数接口对应于标准C语言中的malloc和free,但是它们内部的具体实现却有多种方式。FreeRTOS实际上有5种实现动态内存分配的方式,可以由用户选择使用哪一种。下面分别来介绍它们的异同。

Heap_1方式:

它是5种方法中最简单的,运行效率最高;只支持申请内存,不允许释放;具有时间确定性,不会产生内存碎片;虽然它不支持释放,但是在嵌入式系统下编程一般情况下也够用,因为无论是任务创建、信号量创建等等,在创建之后一般很少需要删除,也就不用释放内存了。

Heap_2方式:

支持内存申请、内存释放;但不支持内存碎片整理(也就是释放后的空闲小内存块不会被合并成大内存块)。

Heap_2方式比较适用于动态分配的内存块大小都是一样的情况,比如每次创建队列时,长度一样,这样不会产生内存碎片。使用时先用pvPortMalloc函数申请内存,得到内存块指针后,再用静态方式创建资源,使用完之后用vPortFree函数释放内存。

Heap_3方式:

对编译器提供的malloc和free进行了封装,需要编译器提供malloc和free的实现。

Heap_4方式:

支持内存申请、内存释放;并且支持内存碎片整理。

Heap_5方式:

这种方式是在heap_4的基础上,增加了对不连续的内存区的支持,也就是堆空间可以是不连续的空间;比如我们单片机内部有SRAM,外部也可以挂载SRAM或SDRAM,如果想把这样两片不连续的地址空间都管理起来,可以用heap_5方式来进行动态内存管理。

使用heap_5方式进行动态内存管理时,需调用vPortDefineHeapRegions函数进行初始化,之后才能调用申请内存、动态创建任务、动态创建信号量之类的申请内存操作。

FreeRTOS的堆空间大小由configTOTAL_HEAP_SIZE宏来确定;除了heap_3方式,其他的几种内存分配方式,都是在这个堆空间里分配的。

使用FreeRTOS的堆空间作为动态内存时(也就是除heap_3之外),可以用xPortGetFreeHeapSize()函数来获取剩余可用堆空间的大小。使用heap_4或heap_5时,可以用xPortGetMinimumEverFreeHeapSize()函数来获取历史剩余可用空间的最小值。

2)编程试验

下面我们来编写一个程序试验freeRTOS的动态内存分配功能。

首先创建工程,默认情况下,cubemx中freeRTOS的堆大小定义为3072字节,使用heap_4方式,我们不修改它,生成keil工程:

生成keil工程后,可以看到源文件中有heap_4.c文件;而且FreeRTOSConfig.h文件中的configTOTAL_HEAP_SIZE宏定义为3072:

在任务中编写如下代码,申请、释放内存,并打印剩余内存空间大小:

程序运行的结果如下图所示:

初始时,内存堆中有1216字节的可用空间;

执行申请10字节空间后,减小到了1192字节;这里不是减小10字节,一方面是因为freeRTOS中申请内存时要8字节对齐,另一方面是因为管理已申请的内存块也需要一定的空间;

执行动态创建一个信号量后,减小到了1112字节;

释放申请的空间后,可用空间回到了1216字节;

最后打印历史可用空间的最小值,1112字节。

可以看到,动态申请内存空间时,堆中的可用空间也是相应变化的。

好了,本节的内容就到这里了。

如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FreeRTOS 中进行动态内存申请,可以使用 FreeRTOS 内置的内存管理函数。FreeRTOS 提供了两种内存管理方案:heap_1 和 heap_5。 1. heap_1:heap_1 是最简单的内存管理方案,它使用 C 标准库中的 malloc() 和 free() 函数来实现内存的分配和释放。你可以通过在 FreeRTOSConfig.h 文件中定义 configUSE_MALLOC 宏来启用 heap_1 内存管理方案。 2. heap_5:heap_5 是更高级的内存管理方案,它使用 FreeRTOS 内置的内存管理函数 pvPortMalloc() 和 vPortFree() 来实现内存的分配和释放。heap_5 允许你通过定义 configAPPLICATION_ALLOCATED_HEAP 宏来指定一个连续的内存区域供 FreeRTOS 作为堆内存使用。 以下是在 FreeRTOS 中进行动态内存申请的示例代码: ```c #include "FreeRTOS.h" #include "task.h" void vTaskFunction(void *pvParameters) { // 动态分配内存 int *ptr = (int *)pvPortMalloc(sizeof(int)); if (ptr != NULL) { // 内存分配成功,可以进行操作 *ptr = 123; // ... // 释放内存 vPortFree(ptr); } vTaskDelete(NULL); } int main(void) { // 创建任务 xTaskCreate(vTaskFunction, "Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL); // 启动调度器 vTaskStartScheduler(); return 0; } ``` 在上述示例中,任务函数 vTaskFunction() 中使用 pvPortMalloc() 函数动态分配了一个 int 类型的内存,并在使用完后通过 vPortFree() 函数释放内存。请注意,内存的释放要确保在不再使用时执行,以避免内存泄漏。 需要注意的是,动态内存分配是一项复杂的任务,可能涉及到内存碎片、多任务竞争等问题。因此,在使用动态内存时,需谨慎规划和管理,以确保系统的可靠性和稳定性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值