【FreeRTOS】内存管理简单介绍

有没有想过什么移植FreeRTOS时,为什么有多种的内存文件,我们工程只使用Heap_4,其他的有什么用?每个的区别是什么?FreeRTOS是一种流行的实时操作系统,广泛应用于嵌入式系统开发中。在嵌入式系统中,内存管理是一个非常重要的问题,因为资源有限,必须合理地分配和使用内存。本文将介绍FreeRTOS中的内存管理机制,并给出一些通俗易懂的例子。
【FreeRTOS】内存管理简单介绍_第1张图片


文章目录

    • 1. 内存管理
      • 1.1 静态创建任务
    • 2. 内存管理文件
    • 3. 动态内存管理
    • 总结


系统移植的文章可以查看这个:
【FreeRTOS】FreeRTOS移植stm32详细步骤介绍


1. 内存管理

在FreeRTOS中,创建任务有两种方式:静态创建任务动态创建任务

1.1 静态创建任务

静态创建任务是在编译时为任务分配固定大小的内存块。通过定义任务时的参数来指定任务所需的栈空间大小。静态创建任务的函数是xTaskCreateStatic(),示例如下:

TaskHandle_t xTaskCreateStatic(
    TaskFunction_t pxTaskCode,
    const char *pcName,
    const uint32_t ulStackDepth,
    void *pvParameters,
    StackType_t *puxStackBuffer,
    StaticTask_t *pxTaskBuffer
);

其中,pxTaskCode是任务函数的指针,pcName是任务的名称,ulStackDepth是任务栈的大小,pvParameters是传递给任务函数的参数,puxStackBuffer是任务栈的起始地址,pxTaskBuffer是任务控制块的起始地址。通过静态创建任务,可以在编译时为任务分配固定大小的内存块,避免了动态内存分配的开销和风险。


2. 内存管理文件

【FreeRTOS】内存管理简单介绍_第2张图片

  1. heap_1.c:这是最简单的内存管理实现,它使用静态数组作为堆内存,只能申请,不能释放,就是只实现了malloc功能,没有实现free功能。实现的原理就是定义一个大数组,然后将合适的空间静态的分配给每个任务,如果某个任务或队列信号量等删除了,那么这个空间也没办法释放,所以它适用于只创建,不删除的系统中。

  2. heap_2.c:这是对heap_1.c的改进,它支持动态内存分配和释放,但没有内存块合并的功能。跟Heap_1不一样的是,Heap_2使用最佳匹配算法来分配内存,并且支持了free功能,最佳匹配算法就是加入我要创建一个任务,它需要17字节的空间,算法可以在多个碎片空间内存中找出最佳的空间,例如有20、15、10、5字节的空间,算法就会分配20空间的内存中的17字节给系统使用,剩下的3字节仍然是空闲字节,可以被申请,但是如果一直没有被申请,就形成了内存碎片,所以Heap_2会产生内存碎片。适用于需要动态内存管理的应用场景,但不需要内存块合并的场景。

  3. heap_3.c:这是对heap_2.c的改进,它支持动态内存分配和释放,并且实现了内存块合并的功能。适用于需要动态内存管理的应用场景,且需要内存块合并的场景。

  4. heap_4.c:这是对heap_3.c的改进,它支持动态内存分配和释放,并且实现了内存块合并和分割的功能。Heap_4使用首次适应算法来分配内存,还会将相邻的空闲内存合并成为一个更大的空闲内存,这有助于较少内存的碎片问题,当需要分配一块内存时,FreeRTOS会遍历空闲内存块链表,查找第一个大小大于等于所需内存的空闲内存块。如果找到了满足条件的空闲内存块,FreeRTOS会将其分割成两部分,一部分用于分配,另一部分保留为剩余的空闲内存块。如果没有找到满足条件的空闲内存块,FreeRTOS会根据需要进行堆内存扩展,以满足分配要求。分配完成后,FreeRTOS会返回分配的内存块的起始地址。。适用于需要动态内存管理的应用场景,且需要内存块合并和分割的场景。

  5. heap_5.c:这是最复杂的内存管理实现,它支持动态内存分配和释放,并且实现了内存块合并、分割和按需增减堆内存的功能。适用于需要灵活管理堆内存的应用场景,但需要更多的内存管理开销。

我们很多情况下都是使用Heap_4,有多块内存会使用Heap_5,其他的很少用到。


3. 动态内存管理

动态内存管理是指在运行时根据需要动态分配内存。在FreeRTOS中,可以使用内置的内存管理器来实现动态内存分配。内存管理器提供了两个函数:pvPortMallocvPortFree,分别用于分配和释放内存。

例如,下面是一个动态分配内存的示例:

#include "FreeRTOS.h"
#include "task.h"

void vTaskFunction(void *pvParameters) {
    char *pcBuffer = pvPortMalloc(1024);
    if (pcBuffer != NULL) {
        // 使用内存
    }
    vPortFree(pcBuffer);
}

int main() {
    xTaskCreate(vTaskFunction, "Task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
    vTaskStartScheduler();
    return 0;
}

在任务函数中,使用pvPortMalloc函数分配了一个大小为1024字节的内存块,并将其赋值给pcBuffer指针。如果分配成功,就可以使用该内存块。最后,使用vPortFree函数释放内存块。


总结

FreeRTOS提供了静态内存管理和动态内存管理两种方式,可以根据具体情况选择合适的方式。静态内存管理可以避免动态内存分配的开销和风险,但需要在编译时为任务分配固定大小的内存块。动态内存管理可以根据需要动态分配内存,但可能存在内存碎片和分配失败的风险。在实际开发中,应该根据具体情况选择合适的内存管理方式。

你可能感兴趣的:(小黑与物联网,数据库,linux,开发语言)