动态内存管理算法 DSA,Dynamic storage allocation。RTOS 一般情况下动态内存使用malloc申请分配,但是存在两个缺陷:
- 由于分配算法的复杂度,分配的时间不定;
- 在不断申请、释放的过程中,容易因为内存对齐而产生碎片化内存;
这两个缺陷在实时操作系统中是不允许的,所以操作系统必须提供一套有效、合理、时间可确定的动态内存管理机制。
既然传统malloc存在两个缺陷,那就抱着解决这两个缺陷的目的出发,去建立一套更适合于嵌入式系统的动态内存管理系统。目前有两种不同的解决方案:
- 动态内存堆管理算法(mmheap),用于不定长分配
- 静态内存池管理算法(mmblk),用于定长分配
mmheap 一般采用 TLSF 算法。TLSF 全称 Two-Level Segregated Fit memory allocator,两级隔离Fit内存分配器,是一款通用的动态内存分配器,专门设计用于满足实时要求。tlsf source code。具有以下特点:
- malloc,free,realloc,memalign的算法复杂度变为O(1);
- 每次分配的开销极低(4字节);
- 低碎片化
- 支持动态添加和删除内存池区域
- TLSF主要采用两级位图(Two-Level Bitmap)与分级空闲块链表(Segregated Free List)的数据结构管理动态内存池(memory pool)以及其中的空闲块(free blocks),用Good-Fit的策略进行分配。
需要注意:
- TLSF算法分配速度不一定快,只是说能保证分配的时间是个常数(malloc不能保证);
- TLSF也叫多内存堆管理算法,支持动态增加或者删除多块不连续的内存,将它们作为一个内存堆使用;
静态内存池就是将一块内存划分为n个大小相等的块,用户可以动态的申请、释放一个块,假装在使用动态内存。

TLFS 采用两级链表的形式来加快查找:
- 第一级链表 First List (简称)。第一层将空闲内存块的大小根据2的幂进行分类,如(16、32、64…),第一级的索引值决定了这一级内存块的大小,范围为 [2i,2(i+1)] ;第一级索引值计算:
= min(, 31) - 第二级链表 Second List (简称)。第二层链表在第一层的基础上,按照一定的间隔,线性分段,其范围应该在1-32,对于32bit的处理器,第二级的索引值一般为4或者5(经验值)。

例如上图分为和两级索引,和的每个bit代表是否被使用:
- 分为8级。
- 分为4级。这里说明下,图中分了8个小区,我们计算sl时会将8个小区合为4个小区;
比如这一段:
- 第一级的为,次高位为1,次高位对应着这一段,说明这一段有空闲块。
- 第二级链表分为4个小区间,每一级的链表都有一个bitmap用于标记对应的链表中是否有内存块。位,其对应着这个区间有空闲块,即下面的89 Byte。
通过两级索引来查找或释放内存,malloc与free的所有操作花费是个时间常数,时间响应复杂度都为;
内存块的控制头,每个内存块不论是 还是 状态都需要一个控制头:
内存池的控制头,也支持多个内存池链接到一起:
- init_memory_pool()
经过 process_area() 初始化以后,内存池中的数据结构:

初始化时一共创建了3个内存块:
- 。系统内存块不会释放,用来存储内存池控制头部 指向的 存储空间。
- 。用户可用的内存块,后面用户可分配得到的内存都来自于这一块内存。
- 。系统内存块不会释放,表示当前内存池的结束, 会指向这里。
每个内存块的头部都是 控制结构,实际数据从 开始存储。
在 process_area() 初始化以后,就会调用 free_ex() 函数将内存块 释放给内存池。我们继续分析具体过程:
经过 free_ex() 以后内存池的状态:

malloc 流程就非常清晰和简单了,主要流程就在二级空闲链表 中查找合适大小的空闲内存块并分配。
其中一个注意的点就是如果分配得到的是大块,还有一个切割的过程:
1.动态内存和静态内存管理机制
2.uC/os内存优化——TLSF算法
3.tlsf github
4.TLsf Documentation
5.实时系统动态内存算法分析dsa(一)
6.实时系统动态内存算法分析dsa(二)——TLSF代码分析
版权声明:
本文来源网络,所有图片文章版权属于原作者,如有侵权,联系删除。
本文网址:https://www.mushiming.com/mjsbk/10844.html