加载中...
Featured image of post 嵌入式系统内存池

嵌入式系统内存池

内存池

内存池管理库 (Pool.c/Pool.h)

👇🏻源码下载

概述

一个轻量级固定大小内存块管理库,适用于嵌入式系统或高频内存分配场景。通过预分配内存和双向链表管理,提供高效的内存分配与释放功能。内存池使用双向链表管理空闲块,并支持相邻空闲块的自动合并,有效减少内存碎片。

内部实现原理

数据结构

内存块结构体 (pool_block_t)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
typedef struct pool_block_t
{
    struct pool_block_t *Block_Prev; // 前一个块指针
    struct pool_block_t *Block_Next; // 后一个块指针

    struct
    {
        block_state_t Block_State:1; // 块状态,0表示空闲,1表示占用
        uint16_t Blocks_Num:15;      // 连续块数量
    } Block_Info;
} pool_block_t;

内存池管理结构体 (mempool_t)

1
2
3
4
5
6
7
8
typedef struct
{
    pool_block_t *Mempool_FreeBlockHead; // 空闲块链表头指针
    uint32_t Mempool_Busy;              // 已占用块数量
    uint32_t Mempool_Free;              // 空闲块数量
    uint8_t *Mempool_Total;             // 内存池总地址指针
    pool_block_t *Mempool_Block_Info;   // 块信息数组指针
} mempool_t;

关键算法

内存分配

  1. 单块分配 - 直接从空闲链表头部获取一个块,时间复杂度O(1)
  2. 多块分配 - 查找连续的空闲块,并从空闲链表中移除

内存释放

  1. 空闲块合并 - 检测并合并左右相邻的空闲块
  2. 链表维护 - 将释放的块重新加入空闲链表

内存池完整性检查

  1. 空闲块计数验证 - 确保记录的空闲块数量与实际一致
  2. 链表环路检测 - 使用快慢指针算法检测链表是否有环
  3. 节点有效性检查 - 验证每个节点指针是否在有效范围内

功能特性

  • ✅ 固定块大小内存管理
  • ✅ 双向链表维护空闲块
  • ✅ 内存碎片合并优化
  • ✅ 内存池完整性检查
  • ✅ 清零分配的内存块
  • ✅ 支持连续多块分配
  • ✅ 自动合并相邻空闲块

快速开始

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 初始化内存池(块大小64字节,1024个块)
if(!MemPool_Init(64, 1024)) {
    // 错误处理
}

// 分配内存
void* ptr = MemPool_Malloc(128); // 分配128字节(2个块)

// 使用内存...

// 释放内存
MemPool_Free(ptr);

// 销毁内存池
MemPool_Deinit();

API参考

初始化/销毁

函数 描述 参数 返回值
MemPool_Init() 初始化内存池 block_size: 块大小(字节)
block_num: 块数量
true: 成功
false: 失败
MemPool_Deinit() 释放内存池资源
MemPool_Init_Default() 使用默认参数初始化(64K字节,1024块) 同MemPool_Init()

内存操作

函数 描述 参数 返回值
MemPool_Malloc() 分配内存 size: 需要分配的字节数 非NULL: 内存指针
NULL: 分配失败
MemPool_Free() 释放内存 ptr: 要释放的内存指针 true: 成功
false: 失败

设计优势

  1. 高效分配 - O(1)时间复杂度分配单个块
  2. 碎片合并 - 自动合并相邻空闲块,减少内存碎片
  3. 安全校验 - 包含内存池完整性检查,防止内存损坏
  4. 预分配机制 - 避免运行时内存碎片和分配失败
  5. 双向链表 - 高效的空闲块管理和快速的块移除操作

内部优化

  1. 快慢指针检测 - 高效检测链表环路,防止内存池损坏
  2. 内联函数 - 关键分配和释放函数使用内联优化性能
  3. 位域结构 - 使用位域优化内存块信息存储
  4. 自动清零 - 分配的内存块自动初始化为零

使用限制⚠️

  1. 仅支持固定块大小分配
  2. 非线程安全,多线程环境需额外同步
  3. 初始化后无法动态扩展内存池大小
  4. 最大支持32767个连续块(受Blocks_Num字段限制)

典型应用场景

  • 嵌入式系统内存管理
  • 网络数据包缓冲
  • 实时任务调度
  • 高频内存分配/释放场景
  • 对象池实现
  • 消息队列缓冲区

示例配置

1
2
#define MEMPOOL_BLOCK_SIZE 64   // 每个块64字节
#define MEMPOOL_BLOCK_NUM 1024  // 共1024个块

性能提示

🔹 分配单个块比多个连续块更快,单块分配为O(1)复杂度  
🔹 释放时会自动合并相邻空闲块,减少内存碎片  
🔹 调试时可启用`DEBUG`宏进行内存池完整性检查  
🔹 内存分配前会自动清零,无需手动初始化  
🔹 内存池放置在SRAM区域,提高访问速度  

实现细节

内存布局

内存池由两部分组成:

  1. 数据区域 - 存储实际数据的连续内存空间
  2. 管理区域 - 存储每个块的元数据信息

空闲块管理

  • 使用双向链表连接所有空闲块
  • 新分配的块从链表头部获取
  • 释放的块添加到链表头部

连续块分配

当需要分配多个连续块时:

  1. 扫描内存池查找连续空闲块
  2. 从空闲链表中移除这些块
  3. 更新第一个块的Blocks_Num字段

内存释放与合并

释放内存时会检查左右相邻块:

  1. 如果有相邻空闲块,从空闲链表中移除
  2. 合并所有相邻空闲块为一个大块
  3. 将合并后的大块添加到空闲链表头部
本博客已稳定运行 小时 分钟
共发表 11 篇文章 · 总计 200.14 k 字
最近一次更新时间:2025-09-18 20:24