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

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

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

1、BlockLink_t结构体和链表指针

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

  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大小进行排序的。源码

 

2、内存分配策略内存管理

 

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

 

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

 

  pvPortMalloc()核心代码:

 

3、内存回收机制

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

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

 

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

  vPortFree()核心代码:

 

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

相关文章
相关标签/搜索