轻量级操作系统FreeRTOS的内存管理机制(二)

  本文由嵌入式企鹅圈原创团队成员朱衡德(Hunter_Zhu)供稿.

  上一篇文章中介绍了FreeRTOS多种内存管理机制中最简单的一种:全局声明一个静态数组ucHeap,然后通过指针偏移记录空间的分配情况,在这种内存机制下无法对内存进行释放。同时也介绍了内存操作过程中字节对齐的细节,本篇文章将会对FreeRTOS源码中第二种内存管理机制heap2.c进行讲解,在heap2.c中同样使用一个全局静态数组ucHeap来表示内存,heap2.c内存管理机制较heap1.c而言增加了内存释放的功能,通过使用链表对内存进行有效管理。

一、BlockLink_t结构体和链表

  在hesp2.c中引入了一个重要结构体:

  BlockLink_t结构体用来描述一块空闲空间的信息,它放在空闲块中的前面部分,xBlockSize表示空闲块空间的大小,空间中供程序用的大小为:xBlockSize-sizeof(BlockLink_t)

 

  描述空闲块信息的所有BlockLink_t结构体根据xBlockSize按小到大连接成链表。在heap2.c中,这个链表的开头和结尾节点分别是xStartxEnd,初始化时heap2.c中的链表结构如下:

 

  初始状态下,链表中只有3个节点,xStart是链表的头节点;第二个节点位于内存实际有效分配空间的前面部分,这个BlockLink_t结构体描述了实际有效分配空间的信息,如这里xBlockSize的值为configADJUSTED_HEAP_SIZE,即初始时整块可用空间的大小;最后一个节点为xEnd,它的下一个节点指向NULLxBlockSize值设置为configADJUSTED_HEAP_SIZE是因为链表是按xBlockSize大小进行排序的。

 

二、内存分配策略

 

  heap2.c内存分配的整体思路是:空闲块通过链表结构进行管理,当需要分配一块内存时,遍历链表(链表中的节点已经按空闲块大小进行排序),找到第一块够大的空闲块进行分配,从链表中移除出来,同时检查这块空间是否过大,如果过大就将空闲块进行切割,然后将剩下部分重新用BlockLink_t描述并插入到链表中。

 

  下图是应用程序请求分配8个字节空间后的链表和内存空间结构示意图:

 

  pvPortMalloc()核心代码:

 

三、内存回收机制

  heap2.c内存回收的整理思路:根据应用程序提供的空间地址,基于这个地址加上sizeof(BlockLink_t)字节偏移可以得到原来空闲块的首地址,然后再将空闲块的BlockLink_t结构体按小到大的顺序插入到空闲块链表中。

  下面两图表示了程序释放8字节空间后的链表和内存空间结构示意图:

 

   下图展示了经过多次内存分配和回收后的链表和内存空间结构示意图:

  vPortFree()核心代码:

 

  可以看出,heap2.c虽然支持内存回收,但是回收内存时不进行相邻空闲块的合并,因此这种策略会导致内存碎片,系统运行久了会出现无法分配过大的连续空间的情况,heap4.c中内存管理机制就是为了弥补这种缺陷而诞生的,它在heap2.c的基础上增加了连续空闲块合并的功能,下一篇会继续进行分析。

 

 

posted @ 2017-04-22 18:57  吴跃前  阅读(962)  评论(0编辑  收藏  举报