内存管理
概览
背景:每当任务、队列或是信号量被创建时,内核需要进行动态内存分配。
调用标准的malloc()和free()库函数,必须承担以下若干问题:
- 在小型嵌入式系统中可能不可用。
- 具体实现可能会相对较大,会占用较多宝贵的代码空间。
- 通常不具备线程安全特性。
- 具有不确定性。每次调用的时间开销都可能不同。
- 会产生内存碎片。
- 使得连接器配置得复杂。
解决方案:FreeRTOS将内存分配作为可移植层面。
- 内核请求内存——调用pvPortMalloc(),而不是直接调用malloc();
- 释放内存——调用vPortFree(),而不是直接调用free()
- 在小型嵌入式系统,通常是在启动调度器之前创建任务、队列和信号量。这样,动态分配内存只会出现在应用程序真正开始执行实际功能之前,而且内存一旦分配就不会再释放,这样选择内存分配方案是就不必考虑一些负载的因素,如确定新与内存碎片等,只需要从性能上考虑,如代码大小和简易性。
内容
- FreeRTOS在什么时候分配内存。
- FreeRTOS提供的三种内存分配方案范例。
内存分配方案范例
Heap_1.c
heap_1.c实现一个非常基本的pvPortMalloc()版本,而且没有实现vPortFree()。
分配方案:将FreeRTOS的内存堆空间看作一个简单的数组。
优点:具有确定性。
缺点:以一个巨型数组会让整个应用程序看来耗费很多内存,即使在数组没有进行任何实际分配之前。
实现方法:为每个创建的任务在堆空间上分配一个任务控制块(TCB)和一个栈空间。
Heap_2.c
分配方案:使用有configTOTAL_HEAP_SIZE定义大小的简单数组,采用最佳匹配算法来分配内存,并支持内存释放。
缺点:耗费许多内存资源,容易产生内存碎片。
应用:是和重复创建与删除具有相同栈空间任务的应用程序。
Heap_3.c
Heap_3.c简单调用了标准库函数malloc和free,但通过暂时挂起调度器使得函数调用具有备线程安全特性。