一种巧妙的内存池算法(HeapBlock)

本文介绍了一种用于频繁分配和释放相同大小数据块的内存管理算法,特别适用于GUI库中的窗口结构和SOCKET结构。通过预先分配内存并进行特定初始化,该算法能在不增加大量额外开销的情况下,实现高效的数据块管理和回收。

在一个简单的GUI库中看到的算法,非常巧妙,适用于需要频繁分配和释放相同大小数据块的情况,如GUI库中的窗口结构,SOCKET结构等,算法额外开支极小。

  1. typedef DWORD HBLOCKHEAP; 
  2. typedef unsigned char BYTE, *PBYTE
  3.  
  4. //使用之前需要先分配一整块内存,并调用此函数进行初始化,初始化后将形成一个链,只是这个链没有前后指针, 
  5. //指针数据保存在数据块实体数据前4字节中 
  6. HBLOCKHEAP BlockHeap_Initialize(void* buffer, int buffersize, int blocksize) 
  7.     PBYTE pBlock = (PBYTE)buffer; 
  8.  
  9.     for(buffersize -= blocksize; pBlock - (PBYTE)buffer < buffersize ; pBlock += blocksize) 
  10.     { 
  11.              //此处将后一块的位置保存在前一块的前4字节中,(PBYTE*)pBlock的转换只是为了将pBlock暂时解释成BYTE*,才能赋值4字节内存地址 
  12.         *(PBYTE*)pBlock = pBlock + blocksize; 
  13.          } 
  14.          *(PBYTE*)pBlock = NULL;//最后一块的下一块为空块 
  15.     return (HBLOCKHEAP)buffer;//返回此链的首块,此值需要调用者保存 
  16.  
  17.  
  18. //从内存池中分配数据时,直接将链首返回给调用者,同时将链首指向的下一块指定为新的链首 
  19. void* BlockHeap_Alloc(HBLOCKHEAP* pHeap) 
  20.     void* pBlock = (void*)(*pHeap); 
  21.  
  22.     if(pBlock) 
  23.         *pHeap =(HBLOCKHEAP)( *(PBYTE*)(*pHeap) ); 
  24.  
  25.     return pBlock; 
  26.  
  27.  
  28. //释放时将要释放的块指定为新的链首,并指向原链首即可 
  29. void BlockHeap_Free(HBLOCKHEAP* pHeap, void* pBlock) 
  30.     *(PBYTE*)pBlock = (PBYTE)(*pHeap); 
  31.     *pHeap = (HBLOCKHEAP)pBlock; 
  32.  
  33.  
  34.  
  35. //基本的调用示例 
  36. typedef struct
  37.     int a; 
  38.     int b; 
  39.     int c; 
  40.     ... 
  41. }SOCKET, *PSOCKET; 
  42.  
  43.  
  44. static SOCKET s_sockets[100];    //先分配的内存 
  45. static HBLOCKHEAP s_hSockets;    //保存链首的变量 
  46.  
  47. //初始化并得到链首 
  48. s_hSockets = BlockHeap_Initialize(s_sockets, sizeof(s_sockets), sizeof(s_sockets[0])); 
  49. //分配内存 
  50. SOCKET *sock = BlockHeap_Alloc(&s_hSockets); 
  51.  
  52. //其它操作... 
  53.  
  54.  
  55. //释放内存 
  56. BlockHeap_Free(&s_hSockets, sock); 

### LWIP 内存管理算法实现分析 LWIP 是一个轻量级的 TCP/IP 协议栈,其内存管理模块设计灵活且高效,支持多种不同的内存分配策略。以下是关于 LWIP 内存管理算法的具体实现分析: #### 1. 内存堆 (Heap Memory) 管理 LWIP 提供了一种基于 C 运行时库的内存堆管理机制,允许开发者通过 `malloc` 和 `free` 函数动态分配和释放内存[^1]。这种模式下,内存堆被初始化为一大块连续的内存区域,在需要时按需切割成不同大小的内存块。 - **优点**: - 动态调整内存块大小,减少碎片化风险。 - 支持任意大小的内存请求,灵活性高。 - **缺点**: - 如果频繁申请和释放内存可能导致严重的内存碎片问题。 - 性能在嵌入式环境中可能不如静态分配方案。 ```c // 初始化内存堆 void mem_init(void); ``` #### 2. 内存池 (Memory Pool) 管理 为了提高性能并降低内存碎片化的可能性,LWIP 引入了固定的内存池管理方式。在这种模式下,预先分配一定数量的固定大小内存块,并将其存储在一个链表中[^3]。每次内存请求都会从这些预分配的内存块中取出一个,而不再依赖于动态分配。 - **优点**: - 预先分配内存块,减少了运行时的内存分配时间。 - 不会产生内存碎片,适合资源受限的嵌入式环境。 - **缺点**: - 对于不确定大小的内存需求不够灵活。 - 若内存池耗尽,则无法满足后续的内存请求。 ```c // 定义内存池结构体 struct memp { u8_t *blocks; /* 所有内存块组成的数组 */ struct memp_block *next_free; /* 下一个可用的空闲块指针 */ }; ``` #### 3. 宏定义控制策略选择 LWIP 使用多个宏定义来决定具体的内存管理策略。例如: - **MEMP_MEM_MALLOC**: 当该宏设置为 1 时,表示启用从内存堆中分配内存池的功能[^4]。此时,内存池中的每一个块实际上是由内存堆动态分配而来。 - **MEM_USE_POOLS**: 同样用于切换到另一种内存管理模式,即将内存堆划分为若干个固定大小的子池[^2]。这种方式能够进一步优化内存利用率,尤其适用于小型设备。 需要注意的是,这两个选项互斥,不能同时开启。 #### 4. 堆与池混合使用的场景 某些情况下,开发人员可以选择结合两种方法的优点,既利用内存堆处理不可预测的大容量数据传输,又依靠内存池保障实时性和稳定性。具体做法是在编译阶段合理配置相关参数以及调用接口函数完成初始化过程。 --- ### 示例代码展示 下面给出一段简单的演示如何初始化 LWIP 的内存管理系统及其核心部分逻辑片段: ```c #include "lwip/mem.h" #include "lwip/memp.h" #define MEM_SIZE (16*1024) // 设置总内存大小为16KB #define MEMP_NUM_PBUF 16 // PBUF 类型对象的数量限制 int main() { // 步骤一:启动常规内存堆服务 mem_init(); // 步骤二:创建指定类型的内存池实例 memp_init(); return 0; } ``` 以上程序展示了最基本的框架搭建流程,实际应用还需考虑更多细节因素比如错误检测等环节。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值