在FreeRTOS8.0.1这个版本中,一共有四个内存堆模型。这一次讲的就是第二个模型Heap_2.c。从一开始就可以看到注释中对Heap_2的模型解释:这是对pvPortMalloc()和vPortFree()的简单实现,除了可以分配内存之外,还可以对已分配的内存进行回收,但相邻空闲块不会进行合并,因此会造成一定的内存碎片。
(A sample implementation of pvPortMalloc() and vPortFree() that permits allocated blocks to be freed, but does not combine adjacent free blocks into a single larger block (and so will fragment memory).)
在Heap_2中,由于开始支持对内存进行回收,因此FreeRTOS以空闲块对内存堆进行管理,并且使用了最佳适配算法(best fit algorithm)去进行内存的分配。
首先,还是由内存中开辟一个静态数组ucHeap[ configTOTAL_HEAP_SIZE ]作为FreeRTOS的内存堆。同样也会因为对齐的原因FreeRTOS对内存堆的可用空间进行了调整,并定义了常量configADJUSTED_HEAP_SIZE。(具体已在上一篇《内存管理Heap_1.c》中介绍)
接下来可以留意Heap_2.c中最重要的结构struct A_BLOCK_LINK。由于FreeRTOS用空闲块对内存堆进行管理,于是用这一个结构来形成一条空闲块链表对空闲块进行组织和管理。
/* Define the linked list structure. This is used to link free blocks in order of their size. */
typedef struct A_BLOCK_LINK
{
struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */
size_t xBlockSize; /*<< The size of the free block. */
} BlockLink_t;
这个结构有两个成员,第一个是节点Next指针pxNextFreeBlock,第二个是空闲块大小。一个空闲块就用这样的一个结构节点表示,所有节点通过Next指针形成一条空闲块链表。FreeRTOS还定义了这个链表的头xStart和尾xEnd。
/* Create a couple of list links to mark the start and end of the list. */
static BlockLink_t xStart, xEnd;
与Heap_1不同,在Heap_2中会有一个堆初始化的过程prvHeapInit()。这一个过程被pvPortMalloc()调用,但只被调用一次。主要还是对内存堆进行对齐还有对空闲块表进行初始化工作。下面是它的工作流程。
首先,初始化流程对整个内存堆进行地址对齐工作。对齐的原因的原理与Heap_1一样。