当前位置:网站首页 > 技术博客 > 正文

内存的trfc



动态内存管理算法 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代码分析

版权声明


相关文章:

  • 计算机组成与设计arm版2025-04-13 20:00:59
  • fork()&&fork()2025-04-13 20:00:59
  • xml注释的写法2025-04-13 20:00:59
  • java面试遇到的技术难题2025-04-13 20:00:59
  • mini.parse()2025-04-13 20:00:59
  • 接口自动化测试的步骤2025-04-13 20:00:59
  • python链接mongo2025-04-13 20:00:59
  • 位图索引和普通索引2025-04-13 20:00:59
  • 匈牙利命名法和驼峰命名法好处2025-04-13 20:00:59
  • 开窗函数 mysql2025-04-13 20:00:59