LwIP从入门到放弃之(二)---动态内存管理

无论在哪种系统中,动态内存管理都是一个非常重要的机制,尤其是在LwIP这种需要处理大量数据的协议栈中,显得尤为重要。本章的内容主要介绍在LwIP中两种最基本的内存管理方式:动态内存池管理和动态内存堆管理。
1. 常见的内存分配策略
第一种:系统规定用户在申请内存的时候,申请大小为4、8、16之类的固定值。如下图所示,系统将所有可用区域按照固定大小为单位进行划分,然后用一个简单的链表连接起来。由于所有链表的节点大小相同,所以分配的时候,不需要查找,直接取出第一个节点中的空间分配给用户;同样,内存释放也很简单,只需要将释放的内存空间插入到对应链表的首部即可。
这种方式效率高,时间短,但是用户申请的内存大小必须为某个固定长度,所以不可避免的存在空间的浪费情况。在LwIP中就是采用这种分配方式,称之为动态内存池分配。
内存块划分

第二种:与第一种方式很类似,系统启动时也会在内存中初始化几个如上图所示的内存空间,但是在第二种情况下,系统会把用户申请的内存空间大小划分为几个范围,向上取整。例如,用户需要申请5个字节,系统会在链表2上分配8个字节。这种分配方式会造成一定的空间浪费,但是可以达到很快的分配速度,因为不需要进行链表的遍历。

第三种:系统运行时,各个空闲内存块的大小是随着系统运行而改变的,系统分配给用户的空间随着用户申请的大小而改变。系统刚开始时,整个内存空间就是一个大闲块,随着分配和回收,内存块的大小和数量也会随着改变,如下图所示:
在这里插入图片描述

假设用户需要申请一个大小为n的内存空间,此时系统内部存在多个空闲块,长度都大于n,根据选择方式不同,由三种常见的分配策略:
(1)首次拟合:顾名思义,从空闲块链表头开始查找,找到的第一个大小大于n的空闲块分配给用户,将空闲块剩余空间重新组成一个小的空闲块插入到链表中。空间释放时,只需要将此内存块重新插入到链表头部即可。首次拟合时目前使用最多的分配策略,LwIP也提供这种内存分配方式,称之为内存堆分配。
(2)最佳拟合:这种方式是在遍历空闲块链表时,找到一个长度和n最接近的空闲块分配给用户。这种方式需要遍历链表,内存回收过程比较慢。通常在这种方式下,系统会将空闲空间按照由小到大的顺序组织起来。
(3)最差拟合:从系统最大的空闲块中划分n个字节分配给用户,这种方式也需要遍历链表,通常这种情况下,系统会将空闲块由大到小的顺序组织起来,这样每次分配无需查找,只需要将第一个空闲块分配给用户即可。
2.动态内存池(POOL)
LwIP协议栈内核初始化的时候,会初始化很多种POOL,这个取决于用户的配置方式。把协议栈所有的POOL挨个放在一起,并把它们放在一片连续的区域,这呈现给用户的就是一个巨大的缓冲池。池子内部的组织应该是这样的:开始放了A类型的POOL池a个,接着是B类型的POOL池b个,再接着是C类型的POOL池c个……
系统中,与缓冲池相关的全局数据变量或类型如下表所示,读者可以自己去查看协议栈代码,本文就不做展开。(因为详细说,我怕写不下,哈哈)。

3.动态内存堆
上文说到,动态内存堆的内存分配方式属于首次拟合,只要找到一个比用户请求空间大的空闲块,就从中割出合适的块,并将剩余的部分返回至动态内存堆中。在这种模式下,用户申请的内存卡大小具有最小限制,不能小于MIN_SIZE,否则系统将自动把请求空间大小设置为MIN_SIZE。MIN_SIZE过小,会在内存分配的时候达到节省空间的目的,但是会导致大的内存块不断分割成小内存块。内存释放过程是相反的,内存回收函数会查看节点附近的内存块是否空闲,如果空闲则合并成一个大的内存块。采用这种策略,有点是内存浪费少,比较简单,缺点是频繁的动态分配和释放,可能造成严重的内存碎片。对于动态内存的使用,比较推荐的方法是:分配—释放—分配—释放,这种方法能有效减少内存碎片。
如下图所示,在内存堆内部,内存堆管理模块通过在每一个内存块的顶部放置一个小的结构体mem来保存内存块分配信息(注意这个小小的结构体是内存管理模块自动附加上去的,独立于用户的申请大小)。这个结构体拥有三个成员变量,两个指针和一个标志,其定义如下代码所示。next与prev分别指向当前内存块的下一个和上一个内存块(事实上,这两个字段保存的是目的地址的一个偏移量,偏移的基地址是整个内存堆空间的起始地址),used标志表示该内存块是否已被分配。数据类型mem_size_t的定义与整个内存堆大小密切相关。

struct men
{
mem_size_t next;
mem_size_t prev;
u8_t usesd;
};
 

在这里插入图片描述

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值