Skip to content

PING020903/MemoryGroundPlus

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Memory Ground Plus - 静态内存池管理系统

📋 项目简介

Memory Ground Plus 是一个轻量级的静态内存池管理组件,专为嵌入式系统和资源受限环境设计。该组件提供预分配内存的管理功能,支持动态内存块分配、释放以及碎片整理,有效避免内存泄漏和碎片化问题。

背景介绍

需要在堆栈一体的32KSRAM中实现对JPEG文件的解码目标芯片为:WCH582, 使用了picoJPEG这个开源库。由于还需要给蓝牙协议栈提供这个SRAM,故而剩余的 SRAM就颇为捉襟见肘,初始做法是将静态分配内存给组件&模块作为专用缓冲区, 但是发现这样非常消耗SRAM且内存利用率不高,一下就占满了整个SRAM。 随后使用tlsf这个开源库,作为内存管理组件,但是我又忽略了该库的内存控制块的大小, 在WCH58X工具链中,控制块初始大小有3144,我至少需要分配4KB的内存给这个内存管理组件。 于是乎,我精心想要削减SRAM的开销,实际上并没有削减太多,也就削了1KB多一些。 在GitHub上也没有找到符合我当下需求——纯C实现的简单内存管理库。于是我自己花3~4天时间, 实现了本内存管理库。


✨ 主要功能

  • 静态内存池管理:使用预分配的静态内存区域,避免动态内存分配的不确定性
  • 内存块分配与释放:支持可变大小的内存块申请和释放
  • 内存碎片整理:自动查找并利用已释放的空闲块,提高内存利用率
  • 安全性检查:防止重复释放、非法地址释放等错误操作
  • 内存块调整大小:通过 mgp_realloc() 支持动态调整已分配内存块大小
  • 可配置内存对齐:支持自定义对齐字节数(默认 4 字节),适配不同硬件需求
  • 完善的测试套件:包含 27 个测试用例,覆盖基础功能、边界条件、压力测试等场景

⚠️ 使用局限性

在使用本项目前,请仔细阅读以下局限性说明:

🔴 严重限制

  1. 单线程环境限制
    • 当前实现未考虑线程安全
    • 不适合多任务操作系统或多核处理器环境
    • 如需在多线程环境使用,请自行添加互斥锁机制

🟡 重要限制

  1. 内存池大小固定

    • 创建时指定大小后无法动态扩容
    • 必须预先评估最大内存需求
    • 不适合内存需求变化剧烈的应用
  2. 无内存保护标记(当前版本)

    • 临时移除了头尾魔术数保护功能
    • 无法自动检测缓冲区溢出
    • 后续版本将重新实现该功能
  3. 小块内存开销较大

    • 每个内存块需要额外的控制块管理
    • 大量小块分配时内存利用率较低
    • 不适合频繁分配极小内存的场景(如几字节的数据)
  4. 外部碎片问题

    • 虽然有碎片查找机制,但未实现内存紧缩
    • 长期运行且频繁分配释放不同大小的块可能导致碎片积累
    • 可能出现总空闲足够但无连续大块的情况
  5. 无内存初始化

    • 分配的内存不会自动清零或填充特定值
    • 用户必须手动初始化,否则可能包含垃圾数据

🟠 其他限制

  1. 对齐要求:虽然支持自定义对齐字节数,但必须是 2 的幂次方(如 2/4/8/16)
  2. 错误处理:分配失败只返回 NULL,不提供详细错误信息
  3. DEBUG 配置:调试模式需在编译时确定,无法运行时动态调整
  4. 控制块数量:最多支持 32767 个已分配块(short 类型限制)
  5. 嵌入式特殊需求:不支持 MPU 配置、中断上下文保护等功能安全特性

📊 适用场景评估

应用场景 推荐度 说明
嵌入式裸机系统 ✅ 非常适合 单线程、确定性内存需求
RTOS 多任务系统 ⚠️ 需改造 需要添加互斥锁
桌面/服务器应用 ❌ 不推荐 建议使用系统 malloc/free
实时系统 ⚠️ 谨慎使用 需评估最坏分配时间
高并发网络服务 ❌ 不适合 线程安全问题
长期运行设备 ⚠️ 需测试 碎片积累风险
安全关键系统 ❌ 不适合 缺少功能安全特性
教学/学习用途 ✅ 非常适合 代码简洁、原理清晰

💡 改进建议:如需突破这些局限性,可参考代码注释中的扩展点进行修改,或联系作者讨论定制方案。


🏗️ 项目结构

memoryGroundPlus/
├── .lingma/                # Lingma IDE 配置
├── include/
│   ├── memGroundP.h        # 主头文件(API 接口)
│   └── DBG_macro.h         # 调试宏定义
├── sources/
│   ├── main.c              # 主程序入口
│   ├── memGroundP.c        # 内存池核心实现
│   └── mgp_test.c          # 完整测试套件
├── build/                  # 构建输出目录(自动生成)
│   └── bin/
│       └── outputFile.exe  # 编译生成的可执行文件
├── CMakeLists.txt          # CMake 构建配置
├── build.bat               # Windows 一键构建脚本
├── TEST_GUIDE.md           # 测试详细指南
└── README.md               # 本说明文档

📦 依赖项

头文件依赖

头文件 类型 用途
<stdint.h> 标准库 提供 uint8_tuintptr_t 等固定宽度类型
<string.h> 标准库 提供 memsetmemcpy 等内存操作函数
<stdio.h> 标准库 提供 printfsprintf 等输入输出函数
<stdlib.h> 标准库 提供 mallocfreeqsort 等通用工具函数
<assert.h> 标准库 提供断言检查(仅 DEBUG 模式)
memGroundP.h 项目文件 内存池模块公共接口
DBG_macro.h 项目文件 调试日志宏定义

使用的标准库函数

函数 所属库 用途
memset() <string.h> 清空内存区域
memcpy() <string.h> 内存块复制
printf() <stdio.h> 格式化输出
sprintf() <stdio.h> 字符串格式化
malloc() <stdlib.h> 动态内存分配(仅测试中使用)
free() <stdlib.h> 释放动态内存(仅测试中使用)
qsort() <stdlib.h> 快速排序(控制块排序)
rand() <stdlib.h> 生成随机数(压力测试)
srand() <stdlib.h> 设置随机种子
assert() <assert.h> 运行时断言检查

外部依赖

  • 无第三方库依赖:本项目完全基于 C 标准库实现
  • 编译器要求:支持 C11 标准的编译器(如 GCC、Clang、MSVC)
  • 构建工具:CMake 3.10+、Ninja(推荐)或 Make

🚀 快速开始

1. 编译项目

Windows (PowerShell)

.\build.bat

或者手动编译

cd build
cmake .. -G Ninja
cmake --build .

2. 运行测试

编译完成后,可执行文件位于 build/bin/outputFile.exe

.\build\bin\outputFile.exe

3. 在你的代码中使用

#include "memGroundP.h"

// 1. 准备一块静态内存区域
static unsigned char memory_pool[1024];

int main(void)
{
    // 2. 创建内存池
    mgp_t pool = mgp_create_with_pool(memory_pool, sizeof(memory_pool));
    if (pool == NULL) {
        return -1;
    }
    
    // 3. 分配内存
    void *block1 = mgp_malloc(pool, 64);  // 分配 64 字节
    void *block2 = mgp_malloc(pool, 128); // 分配 128 字节
    
    // ... 使用分配的内存 ...
    
    // 4. 释放内存
    mgp_free(pool, block1);
    mgp_free(pool, block2);
    
    return 0;
}

📖 API 接口

核心函数

1. mgp_create_with_pool()

mgp_t mgp_create_with_pool(void *mem, size_t bytes);
  • 功能:使用给定的内存区域创建内存池
  • 参数
    • mem:预分配的内存区域起始地址
    • bytes:内存区域总大小(字节)
  • 返回值:成功返回内存池句柄,失败返回 NULL
  • 最小内存需求sizeof(mgp_pool_t) + sizeof(mgp_ctrl_t) ≈ 72 字节

2. mgp_malloc()

void *mgp_malloc(mgp_t poolAddr, const size_t bytes);
  • 功能:从内存池分配指定大小的内存块
  • 参数
    • poolAddr:内存池句柄
    • bytes:需要的字节数(用户可用大小)
  • 返回值:成功返回内存块指针,失败返回 NULL
  • 实际占用bytes 字节(当前版本无头尾标记)
  • 对齐:自动按 MGP_ALIGN_NUM 配置值对齐(默认 4 字节,可修改)
  • 配置方法:在 memGroundP.h 中修改 MGP_ALIGN_NUM 宏定义

3. mgp_free()

void mgp_free(mgp_t poolAddr, void *p);
  • 功能:释放已分配的内存块
  • 参数
    • poolAddr:内存池句柄
    • p:要释放的内存块指针
  • 注意:释放非法地址会触发错误提示

4. mgp_realloc() [新增]

void* mgp_realloc(mgp_t poolAddr, const void* src, const size_t bytes);
  • 功能:调整已分配内存块的大小
  • 参数
    • poolAddr:内存池句柄
    • src:原内存块指针(可为 NULL)
    • bytes:新的字节数
  • 返回值:成功返回新内存块指针,失败返回 NULL
  • 特性
    • src == NULL 时等同于 mgp_malloc()
    • 扩大时自动复制原数据
    • 缩小时直接返回原指针

5. mgp_canAllocMaxSize()

const size_t mgp_canAllocMaxSize(mgp_t p);
  • 功能:获取内存池可分配的最大内存块大小
  • 参数:内存池句柄
  • 返回值:可分配的最大字节数(用户可用大小)

🧪 测试套件

测试用例分类

等级 测试类型 用例数 说明
Level 1 基础功能测试 4 内存池创建、尺寸查询等
Level 2 内存分配测试 4 单次/多次分配、耗尽测试
Level 3 内存释放测试 4 单次/乱序释放、异常释放检测
Level 4 碎片整理测试 2 碎片再利用、尺寸适配
Level 5 边界条件测试 4 零长度、极小/极大尺寸
Level 6 数据完整性测试 3 边界测试、数据隔离性
Level 7 压力测试 2 大量分配、随机混合操作
Level 8 realloc 测试 4 NULL 指针、扩大、缩小、零尺寸
总计 - 27 通过率:100%

运行测试

#include "memGroundP.h"

int main(void)
{
    // 一键运行所有测试
    mgp_run_all_tests();
    return 0;
}

🔧 配置选项

调试开关

memGroundP.h 中配置:

#define MGP_DEBUG 1  // 启用调试模式(开启 assert 和日志)

内存对齐配置 [重要]

memGroundP.h 中配置对齐字节数:

#define MGP_ALIGN_NUM 4  // 对齐字节数,必须是 2 的幂次方

可选值示例:

  • MGP_ALIGN_NUM = 2:2 字节对齐(最小开销)
  • MGP_ALIGN_NUM = 4:4 字节对齐(默认,适合 32 位系统)
  • MGP_ALIGN_NUM = 8:8 字节对齐(适合 64 位系统或 DMA 传输)
  • MGP_ALIGN_NUM = 16:16 字节对齐(适合 SIMD 指令)
  • MGP_ALIGN_NUM = 32:32 字节对齐(适合缓存行对齐)

注意事项:

  • ⚠️ 必须是 2 的幂次方(如 2, 4, 8, 16, 32...)
  • ⚠️ 修改后需要重新编译整个项目
  • ⚠️ 较大的对齐值会增加内存开销,但可能提升访问性能

memGroundP.cmgp_test.c 中配置详细日志:

#define MGP_CREATE_POOL_DEBUG    0  // 内存池创建调试
#define MGP_CTRL_BLOCK_DEBUG     0  // 控制块调试
#define MGP_FREE_BLOCK_DEBUG     0  // 空闲块查找调试
#define MGP_MEMORY_FREE_DEBUG    1  // 释放操作调试
#define MGP_MEMORY_ALLOC_DEBUG   1  // 分配操作调试

📊 技术特性

内存布局

┌─────────────────────────────────────────────────┐
│  内存池整体布局                                  │
├─────────────────────────────────────────────────┤
│  [mgp_pool_t]  ← 内存池控制结构(头部)          │
│  [mgp_ctrl_t]  ← 控制块表(紧随 pool_t)         │
│  [已分配块 1]  ← 动态分配的内存块                │
│  [已分配块 2]                                    │
│  ...                                           │
│  [未分配空间] ← 剩余可用空间                     │
└─────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────┐
│  单个内存块布局(当前版本)                     │
├─────────────────────────────────────────────────┤
│  [用户数据区]     ← 用户实际使用的部分           │
│                      (由控制块管理)            │
│                      (自动对齐)                │
└─────────────────────────────────────────────────┘

> 💡 注:头尾保护标记功能暂时移除,后续版本将重新实现
>
> 💡 注:内存块地址会自动按 `MGP_ALIGN_NUM` 配置对齐

关键常量

常量 说明
MGP_OK 0 成功
MGP_ERR_ARG -1 参数错误
MGP_ERR_NOMEM -3 内存不足
MGP_ALIGN_NUM 4 默认对齐字节数(可配置)

错误码

#define MGP_OK               0      ///< 成功
#define MGP_ERR_ARG          (-1)   ///< 参数错误
#define MGP_ERR_ALIGN        (-2)   ///< 对齐错误
#define MGP_ERR_NOMEM        (-3)   ///< 内存不足
#define MGP_ERR_CORRUPT      (-10)  ///< 检验损坏(保留)
#define MGP_ERR_NOT_INIT     (-20)  ///< 未初始化

⚠️ 注意事项

  1. 最小分配尺寸:实际分配大小为 bytes 字节(当前版本无头尾标记)
  2. 不支持多线程:当前实现未考虑线程安全,如需在多线程环境使用请自行添加锁机制
  3. 零长度分配:分配 0 字节会触发 assert(预期行为)
  4. 内存池扩容:不支持动态扩容,需在创建时指定足够的大小
  5. 对齐要求:支持自定义对齐字节数,但必须是 2 的幂次方
  6. realloc 使用:调整后的内存块地址可能会变化,需更新引用指针
  7. 性能建议:对于 DMA 传输或缓存敏感应用,建议使用 8/16/32 字节对齐

📝 版本历史

  • v1.1 (2026-04-01)

    • ✨ 新增 mgp_realloc() 函数,支持动态调整内存块大小
    • ✨ 新增可配置内存对齐功能(MGP_ALIGN_NUM 宏)
    • 🛠️ 优化 mgp_getFreeBlock() 逻辑,改进碎片查找算法
    • 🔧 临时移除魔术数保护功能(简化实现)
    • ✅ 测试用例扩展至 27 个,保持 100% 通过率
    • 📝 更新文档和测试指南
  • v1.0 (2026-03-20)

    • ✨ 初始版本发布
    • ✅ 完整的 23 个测试用例,通过率 100%
    • 🛠️ 修复边界条件问题(指针下溢风险)
    • 🛠️ 添加最大分配尺寸检查

🤝 贡献指南

欢迎提交 Issue 和 Pull Request!

如有问题或建议,请查看:


📄 许可证

本项目采用 MIT 许可证(或其他你选择的许可证)


📧 联系方式

  • 作者:___________
  • Email:___________
  • 项目主页:___________

Memory Ground Plus - 让内存管理更可靠!

⬆ 返回顶部

About

Embedded Memory Management Component

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors