采用大块内存池 + mmap映射的管理方式。

一、整体架构设计

memory_manager/
├── include/
│   ├── mem_core.h           # 核心内存管理接口
│   ├── mem_pool.h            # 小内存池管理
│   ├── mem_mmap.h            # 大块MMAP管理
│   └── mem_video.h           # 视频帧专用管理
├── src/
│   ├── mem_core.c
│   ├── mem_pool.c
│   ├── mem_mmap.c
│   └── mem_video.c
└── test/
    └── test_memory.c

二、核心内存管理接口设计

/**
 * @file mem_core.h
 * @brief 核心内存管理接口
 * @details 提供统一的内存分配和释放接口,支持不同内存管理策略
 */
​
#ifndef MEM_CORE_H
#define MEM_CORE_H
​
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
​
/*==================== 内存块类型定义 ====================*/
​
/**
 * @brief 内存块类型枚举
 */
typedef enum {
    MEM_TYPE_SMALL_POOL,     /*!< 小内存池管理 */
    MEM_TYPE_MMAP_BLOCK,     /*!< MMAP大块内存 */
    MEM_TYPE_VIDEO_FRAME,     /*!< 视频帧专用 */
    MEM_TYPE_DMA_BUFFER       /*!< DMA缓冲区 */
} mem_type_t;
​
/**
 * @brief 内存块头部信息
 * @details 每个内存块前都带有此头部,用于管理
 */
typedef struct mem_header {
    uint32_t magic;                    /*!< 魔数,用于校验 */
    mem_type_t type;                    /*!< 内存类型 */
    uint32_t size;                      /*!< 数据区大小 */
    uint32_t block_size;                 /*!< 实际分配大小(含头部)*/
    struct mem_header *next;             /*!< 链表下一节点 */
    struct mem_header *prev;             /*!< 链表上一节点 */
    uint32_t ref_count;                  /*!< 引用计数 */
    uint32_t flags;                      /*!< 标志位 */
    
    /* 统计信息 */
    uint64_t alloc_time;                 /*!< 分配时间戳 */
    void *owner;                         /*!< 所有者标识 */
    const char *file;                    /*!< 分配文件名 */
    int line;                            /*!< 分配行号 */
} mem_header_t;
​
#define MEM_MAGIC 0xDEADBEEF
#define MEM_HEADER_SIZE sizeof(mem_header_t)
​
/*==================== 内存管理器接口 ====================*/
​
/**
 * @brief 内存管理器虚函数表
 */
typedef struct mem_ops {
    void* (*alloc)(void *manager, uint32_t size, uint32_t align);
    void (*free)(void *manager, void *ptr);
    void* (*realloc)(void *manager, void *ptr, uint32_t new_size);
    void (*dump)(void *manager);
    uint32_t (*get_used)(void *manager);
    uint32_t (*get_total)(void *manager);
} mem_ops_t;
​
/**
 * @brief 内存管理器基类
 */
typedef struct mem_manager {
    const char *name;                     /*!< 管理器名称 */
    mem_ops_t *ops;                        /*!< 操作函数表 */
    void *private_data;                    /*!< 私有数据 */
    uint32_t total_size;                   /*!< 总管理内存大小 */
    uint32_t used_size;                    /*!< 已用内存大小 */
    uint32_t peak_used;                    /*!< 峰值使用 */
} mem_manager_t;
​
/* 核心API */
void* mem_alloc(mem_manager_t *mgr, uint32_t size);
void* mem_alloc_align(mem_manager_t *mgr, uint32_t size, uint32_t align);
void mem_free(mem_manager_t *mgr, void *ptr);
void* mem_realloc(mem_manager_t *mgr, void *ptr, uint32_t new_size);
​
/* 调试辅助 */
#define MEM_ALLOC(mgr, size) mem_alloc_debug(mgr, size, __FILE__, __LINE__)
#define MEM_FREE(mgr, ptr) mem_free_debug(mgr, ptr, __FILE__, __LINE__)
​
#endif /* MEM_CORE_H */
/**
 * @file mem_core.c
 * @brief 核心内存管理实现
 */
​
#include "mem_core.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
​
/**
 * @brief 通用内存分配接口
 */
void* mem_alloc(mem_manager_t *mgr, uint32_t size) {
    if (!mgr || !mgr->ops || !mgr->ops->alloc) {
        return NULL;
    }
    return mgr->ops->alloc(mgr->private_data, size, 4);
}
​
/**
 * @brief 对齐内存分配
 */
void* mem_alloc_align(mem_manager_t *mgr, uint32_t size, uint32_t align) {
    if (!mgr || !mgr->ops || !mgr->ops->alloc) {
        return NULL;
    }
    return mgr->ops->alloc(mgr->private_data, size, align);
}
​
/**
 * @brief 带调试信息的内存分配
 */
void* mem_alloc_debug(mem_manager_t *mgr, uint32_t size, 
                      const char *file, int line) {
    mem_header_t *header;
    void *ptr;
    
    ptr = mgr->ops->alloc(mgr->private_data, size + MEM_HEADER_SIZE, 8);
    if (!ptr) return NULL;
    
    header = (mem_header_t*)ptr;
    header->magic = MEM_MAGIC;
    header->size = size;
    header->block_size = size + MEM_HEADER_SIZE;
    header->file = file;
    header->line = line;
    
    struct timeval tv;
    gettimeofday(&tv, NULL);
    header->alloc_time = tv.tv_sec * 1000000 + tv.tv_usec;
    
    mgr->used_size += header->block_size;
    if (mgr->used_size > mgr->peak_used) {
        mgr->peak_used = mgr->used_size;
    }
    
    return (void*)((uint8_t*)ptr + MEM_HEADER_SIZE);
}
​
/**
 * @brief 带调试信息的内存释放
 */
void mem_free_debug(mem_manager_t *mgr, void *ptr, 
                    const char *file, int line) {
    mem_header_t *header;
    void *real_ptr;
    
    if (!ptr) return;
    
    real_ptr = (void*)((uint8_t*)ptr - MEM_HEADER_SIZE);
    header = (mem_header_t*)real_ptr;
    
    if (header->magic != MEM_MAGIC) {
        fprintf(stderr, "Memory corruption detected at %s:%d\n", 
                file, line);
        return;
    }
    
    mgr->used_size -= header->block_size;
    mgr->ops->free(mgr->private_data, real_ptr);
}

三、小内存池管理

/**
 * @file mem_pool.h
 * @brief 小内存池管理器
 * @details 针对频繁分配的小内存块,预分配大块内存池
 */
​
#ifndef MEM_POOL_H
#define MEM_POOL_H
​
#include "mem_core.h"
​
/*==================== 内存池配置 ====================*/
​
#define POOL_MAX_LEVELS 8        /*!< 最大内存块等级 */
#define POOL_MIN_BLOCK_SIZE 32    /*!< 最小块大小 */
#define POOL_MAX_BLOCK_SIZE 4096  /*!< 最大块大小 */
​
/**
 * @brief 内存池块信息
 */
typedef struct pool_block {
    struct pool_block *next;       /*!< 空闲链表指针 */
    uint32_t size;                  /*!< 块大小 */
    uint32_t magic;                 /*!< 魔数 */
} pool_block_t;
​
/**
 * @brief 内存池等级
 */
typedef struct pool_level {
    uint32_t block_size;            /*!< 该等级块大小 */
    uint32_t block_count;           /*!< 块总数 */
    uint32_t free_count;            /*!< 空闲块数 */
    pool_block_t *free_list;        /*!< 空闲块链表 */
    void *blocks_start;             /*!< 块区域起始 */
} pool_level_t;
​
/**
 * @brief 内存池管理器
 */
typedef struct mem_pool_manager {
    mem_manager_t base;              /*!< 基类 */
    
    /* 内存池区域 */
    void *pool_memory;               /*!< 整个内存池起始 */
    uint32_t pool_size;              /*!< 内存池总大小 */
    
    /* 等级管理 */
    pool_level_t levels[POOL_MAX_LEVELS];
    uint32_t level_count;
    
    /* 统计 */
    uint32_t alloc_count;
    uint32_t free_count;
    uint32_t fail_count;
    
    /* 锁 */
    void *lock;
} mem_pool_manager_t;
​
/**
 * @brief 创建内存池管理器
 * @param total_size 内存池总大小
 * @return 内存管理器指针
 */
mem_manager_t* mem_pool_create(uint32_t total_size);
​
/**
 * @brief 销毁内存池管理器
 */
void mem_pool_destroy(mem_manager_t *mgr);
​
#endif /* MEM_POOL_H */
/**
 * @file mem_pool.c
 * @brief 小内存池管理实现
 */
​
#include "mem_pool.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
​
/* 私有操作函数声明 */
static void* pool_alloc(void *mgr, uint32_t size, uint32_t align);
static void pool_free(void *mgr, void *ptr);
static void pool_dump(void *mgr);
static uint32_t pool_get_used(void *mgr);
static uint32_t pool_get_total(void *mgr);
​
/* 操作函数表 */
static mem_ops_t pool_ops = {
    .alloc = pool_alloc,
    .free = pool_free,
    .dump = pool_dump,
    .get_used = pool_get_used,
    .get_total = pool_get_total
};
​
/**
 * @brief 初始化内存池等级
 */
static void init_pool_levels(mem_pool_manager_t *mgr) {
    uint32_t size = POOL_MIN_BLOCK_SIZE;
    uint32_t remaining = mgr->pool_size;
    uint8_t *mem_ptr = (uint8_t*)mgr->pool_memory;
    int level = 0;
    
    while (size <= POOL_MAX_BLOCK_SIZE && level < POOL_MAX_LEVELS) {
        pool_level_t *lvl = &mgr->levels[level];
        uint32_t block_count = remaining / (size + sizeof(pool_block_t));
        
        if (block_count > 0) {
            lvl->block_size = size;
            lvl->block_count = block_count;
            lvl->free_count = block_count;
            lvl->free_list = NULL;
            lvl->blocks_start = mem_ptr;
            
            /* 初始化空闲链表 */
            pool_block_t *prev = NULL;
            for (uint32_t i = 0; i < block_count; i++) {
                pool_block_t *block = (pool_block_t*)mem_ptr;
                block->next = NULL;
                block->size = size;
                block->magic = MEM_MAGIC;
                
                if (prev) {
                    prev->next = block;
                } else {
                    lvl->free_list = block;
                }
                prev = block;
                
                mem_ptr += size + sizeof(pool_block_t);
            }
            
            remaining -= block_count * (size + sizeof(pool_block_t));
            level++;
        }
        
        size *= 2;  /* 每次翻倍 */
    }
    
    mgr->level_count = level;
}
​
/**
 * @brief 创建内存池管理器
 */
mem_manager_t* mem_pool_create(uint32_t total_size) {
    mem_pool_manager_t *mgr;
    
    mgr = (mem_pool_manager_t*)malloc(sizeof(mem_pool_manager_t));
    if (!mgr) return NULL;
    
    memset(mgr, 0, sizeof(mem_pool_manager_t));
    
    /* 分配整个内存池 */
    mgr->pool_memory = malloc(total_size);
    if (!mgr->pool_memory) {
        free(mgr);
        return NULL;
    }
    
    mgr->pool_size = total_size;
    mgr->base.name = "Memory Pool Manager";
    mgr->base.ops = &pool_ops;
    mgr->base.private_data = mgr;
    mgr->base.total_size = total_size;
    mgr->base.used_size = 0;
    mgr->base.peak_used = 0;
    
    /* 初始化等级 */
    init_pool_levels(mgr);
    
    return (mem_manager_t*)mgr;
}
​
/**
 * @brief 查找合适的内存池等级
 */
static pool_level_t* find_suitable_level(mem_pool_manager_t *mgr, 
                                          uint32_t size) {
    for (int i = 0; i < mgr->level_count; i++) {
        if (mgr->levels[i].block_size >= size) {
            return &mgr->levels[i];
        }
    }
    return NULL;
}
​
/**
 * @brief 池内存分配
 */
static void* pool_alloc(void *mgr_priv, uint32_t size, uint32_t align) {
    mem_pool_manager_t *mgr = (mem_pool_manager_t*)mgr_priv;
    pool_level_t *level;
    pool_block_t *block;
    
    /* 加上对齐开销 */
    uint32_t real_size = size + align - 1;
    
    level = find_suitable_level(mgr, real_size);
    if (!level || !level->free_list) {
        mgr->fail_count++;
        return NULL;
    }
    
    /* 从空闲链表取下 */
    block = level->free_list;
    level->free_list = block->next;
    level->free_count--;
    
    mgr->alloc_count++;
    
    /* 返回可用数据区 */
    return (void*)((uint8_t*)block + sizeof(pool_block_t));
}
​
/**
 * @brief 池内存释放
 */
static void pool_free(void *mgr_priv, void *ptr) {
    mem_pool_manager_t *mgr = (mem_pool_manager_t*)mgr_priv;
    pool_block_t *block;
    pool_level_t *level;
    
    if (!ptr) return;
    
    /* 获取块头部 */
    block = (pool_block_t*)((uint8_t*)ptr - sizeof(pool_block_t));
    
    if (block->magic != MEM_MAGIC) {
        fprintf(stderr, "Invalid memory block\n");
        return;
    }
    
    /* 查找所属等级 */
    for (int i = 0; i < mgr->level_count; i++) {
        level = &mgr->levels[i];
        if (block->size == level->block_size) {
            /* 放回空闲链表 */
            block->next = level->free_list;
            level->free_list = block;
            level->free_count++;
            mgr->free_count++;
            return;
        }
    }
    
    fprintf(stderr, "Block size %u not found in pool\n", block->size);
}

四、大块MMAP内存管理

/**
 * @file mem_mmap.h
 * @brief MMAP大块内存管理器
 * @details 使用mmap管理大块内存,适合视频帧等大数据
 */
​
#ifndef MEM_MMAP_H
#define MEM_MMAP_H
​
#include "mem_core.h"
#include <sys/mman.h>
​
/*==================== MMAP配置 ====================*/
​
#define MMAP_MIN_SIZE (1024 * 1024)        /*!< 最小MMAP大小: 1MB */
#define MMAP_ALIGNMENT 4096                  /*!< 页对齐 */
#define MMAP_MAX_BLOCKS 128                   /*!< 最大块数 */
​
/**
 * @brief MMAP内存块
 */
typedef struct mmap_block {
    void *addr;                              /*!< 映射地址 */
    uint32_t size;                            /*!< 块大小 */
    uint32_t used;                            /*!< 已用大小 */
    int fd;                                    /*!< 文件描述符(匿名映射为-1)*/
    uint32_t flags;                            /*!< 映射标志 */
    
    struct mmap_block *next;                   /*!< 下一个块 */
    struct mmap_block *prev;                   /*!< 上一个块 */
    
    /* 统计 */
    uint32_t alloc_count;
    uint32_t free_count;
} mmap_block_t;
​
/**
 * @brief MMAP内存管理器
 */
typedef struct mem_mmap_manager {
    mem_manager_t base;                        /*!< 基类 */
    
    /* 内存块管理 */
    mmap_block_t *blocks;                       /*!< 所有块链表 */
    mmap_block_t *free_blocks;                  /*!< 空闲块链表 */
    uint32_t block_count;
    
    /* 缓存池 */
    mmap_block_t *block_cache;                  /*!< 块缓存数组 */
    
    /* 配置 */
    uint32_t page_size;
    uint32_t min_size;
    
    /* 统计 */
    uint64_t total_mapped;
    uint64_t total_unmapped;
} mem_mmap_manager_t;
​
/**
 * @brief 创建MMAP内存管理器
 * @return 内存管理器指针
 */
mem_manager_t* mem_mmap_create(void);
​
/**
 * @brief 预分配MMAP区域
 * @param mgr 管理器
 * @param size 预分配大小
 * @return 0成功,-1失败
 */
int mem_mmap_prealloc(mem_manager_t *mgr, uint32_t size);
​
/**
 * @brief 销毁MMAP管理器
 */
void mem_mmap_destroy(mem_manager_t *mgr);
​
#endif /* MEM_MMAP_H */
/**
 * @file mem_mmap.c
 * @brief MMAP大块内存管理实现
 */
​
#include "mem_mmap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
​
/* 私有操作函数 */
static void* mmap_alloc(void *mgr, uint32_t size, uint32_t align);
static void mmap_free(void *mgr, void *ptr);
static void mmap_dump(void *mgr);
static uint32_t mmap_get_used(void *mgr);
static uint32_t mmap_get_total(void *mgr);
​
static mem_ops_t mmap_ops = {
    .alloc = mmap_alloc,
    .free = mmap_free,
    .dump = mmap_dump,
    .get_used = mmap_get_used,
    .get_total = mmap_get_total
};
​
/**
 * @brief 创建MMAP管理器
 */
mem_manager_t* mem_mmap_create(void) {
    mem_mmap_manager_t *mgr;
    
    mgr = (mem_mmap_manager_t*)malloc(sizeof(mem_mmap_manager_t));
    if (!mgr) return NULL;
    
    memset(mgr, 0, sizeof(mem_mmap_manager_t));
    
    mgr->base.name = "MMAP Memory Manager";
    mgr->base.ops = &mmap_ops;
    mgr->base.private_data = mgr;
    mgr->base.total_size = 0;
    mgr->base.used_size = 0;
    
    mgr->page_size = sysconf(_SC_PAGESIZE);
    mgr->min_size = MMAP_MIN_SIZE;
    
    /* 初始化块缓存 */
    mgr->block_cache = (mmap_block_t*)calloc(MMAP_MAX_BLOCKS, 
                                              sizeof(mmap_block_t));
    
    return (mem_manager_t*)mgr;
}
​
/**
 * @brief 创建新的MMAP块
 */
static mmap_block_t* create_mmap_block(mem_mmap_manager_t *mgr, 
                                        uint32_t size) {
    mmap_block_t *block;
    void *addr;
    
    /* 页对齐 */
    size = (size + mgr->page_size - 1) & ~(mgr->page_size - 1);
    
    /* 使用匿名映射 */
    addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    
    if (addr == MAP_FAILED) {
        perror("mmap failed");
        return NULL;
    }
    
    /* 从缓存获取块结构 */
    block = &mgr->block_cache[mgr->block_count];
    mgr->block_count++;
    
    block->addr = addr;
    block->size = size;
    block->used = 0;
    block->fd = -1;
    block->flags = 0;
    block->alloc_count = 0;
    block->free_count = 0;
    
    /* 添加到链表 */
    block->next = mgr->blocks;
    if (mgr->blocks) {
        mgr->blocks->prev = block;
    }
    mgr->blocks = block;
    
    mgr->total_mapped += size;
    mgr->base.total_size += size;
    
    printf("MMAP: Created block %p size %u\n", addr, size);
    
    return block;
}
​
/**
 * @brief 查找合适的MMAP块
 */
static mmap_block_t* find_suitable_block(mem_mmap_manager_t *mgr,
                                          uint32_t size) {
    mmap_block_t *block = mgr->blocks;
    
    /* 查找有空闲空间的块 */
    while (block) {
        if (block->size - block->used >= size) {
            return block;
        }
        block = block->next;
    }
    
    /* 没有找到,创建新块 */
    uint32_t new_size = size > mgr->min_size ? size : mgr->min_size;
    return create_mmap_block(mgr, new_size);
}
​
/**
 * @brief MMAP内存分配
 */
static void* mmap_alloc(void *mgr_priv, uint32_t size, uint32_t align) {
    mem_mmap_manager_t *mgr = (mem_mmap_manager_t*)mgr_priv;
    mmap_block_t *block;
    void *ptr;
    uint32_t aligned_size;
    
    /* 对齐到页 */
    aligned_size = (size + mgr->page_size - 1) & ~(mgr->page_size - 1);
    
    block = find_suitable_block(mgr, aligned_size);
    if (!block) return NULL;
    
    /* 在当前块中分配 */
    ptr = (void*)((uint8_t*)block->addr + block->used);
    block->used += aligned_size;
    block->alloc_count++;
    
    mgr->base.used_size += aligned_size;
    
    /* 记录分配信息(在块内存储头部)*/
    mem_header_t *header = (mem_header_t*)ptr;
    header->magic = MEM_MAGIC;
    header->type = MEM_TYPE_MMAP_BLOCK;
    header->size = size;
    header->block_size = aligned_size;
    header->next = NULL;
    header->prev = NULL;
    header->ref_count = 1;
    header->owner = block;
    
    return (void*)((uint8_t*)ptr + MEM_HEADER_SIZE);
}
​
/**
 * @brief MMAP内存释放
 */
static void mmap_free(void *mgr_priv, void *ptr) {
    mem_mmap_manager_t *mgr = (mem_mmap_manager_t*)mgr_priv;
    mem_header_t *header;
    mmap_block_t *block;
    
    if (!ptr) return;
    
    header = (mem_header_t*)((uint8_t*)ptr - MEM_HEADER_SIZE);
    
    if (header->magic != MEM_MAGIC) {
        fprintf(stderr, "Invalid memory header\n");
        return;
    }
    
    block = (mmap_block_t*)header->owner;
    if (!block) return;
    
    /* 这里简单处理:不实际释放,只标记 */
    block->used -= header->block_size;
    block->free_count++;
    
    mgr->base.used_size -= header->block_size;
    
    /* 如果块完全空闲,可以考虑munmap */
    if (block->used == 0 && block->size > mgr->min_size * 2) {
        /* 可以释放大块空闲内存 */
        munmap(block->addr, block->size);
        mgr->total_unmapped += block->size;
        mgr->base.total_size -= block->size;
        
        /* 从链表中移除 */
        if (block->prev) {
            block->prev->next = block->next;
        } else {
            mgr->blocks = block->next;
        }
        if (block->next) {
            block->next->prev = block->prev;
        }
    }
}

五、视频帧专用内存管理

/**
 * @file mem_video.h
 * @brief 视频帧专用内存管理器
 * @details 针对视频帧特点优化的内存管理
 */
​
#ifndef MEM_VIDEO_H
#define MEM_VIDEO_H
​
#include "mem_core.h"
​
/*==================== 视频帧配置 ====================*/
​
#define MAX_FRAME_WIDTH 3840          /*!< 最大宽度 4K */
#define MAX_FRAME_HEIGHT 2160          /*!< 最大高度 4K */
#define MAX_FRAME_FORMATS 8             /*!< 最大格式数 */
#define VIDEO_FRAME_POOL_SIZE 16        /*!< 帧池大小 */
​
/**
 * @brief 视频像素格式
 */
typedef enum {
    PIX_FMT_NV12,       /*!< NV12 YUV420 半平面 */
    PIX_FMT_NV21,       /*!< NV21 YUV420 半平面 */
    PIX_FMT_YUYV,       /*!< YUYV 打包格式 */
    PIX_FMT_RGB24,      /*!< RGB24 */
    PIX_FMT_BGR24,      /*!< BGR24 */
    PIX_FMT_ARGB,       /*!< ARGB32 */
    PIX_FMT_MJPEG,      /*!< MJPEG压缩帧 */
    PIX_FMT_H264        /*!< H.264压缩帧 */
} pixel_format_t;
​
/**
 * @brief 视频帧信息
 */
typedef struct video_frame {
    mem_header_t header;                /*!< 内存头部 */
    
    /* 帧属性 */
    uint32_t width;                      /*!< 宽度 */
    uint32_t height;                     /*!< 高度 */
    pixel_format_t format;                /*!< 像素格式 */
    uint32_t stride;                      /*!< 行跨度 */
    
    /* 时间信息 */
    uint64_t timestamp;                   /*!< 时间戳 */
    uint32_t sequence;                    /*!< 序列号 */
    
    /* 数据区 */
    uint8_t *y_plane;                     /*!< Y平面 */
    uint8_t *uv_plane;                    /*!< UV平面 */
    uint32_t y_size;                       /*!< Y平面大小 */
    uint32_t uv_size;                      /*!< UV平面大小 */
    
    /* 引用计数 */
    uint32_t ref_count;                    /*!< 引用计数 */
    
    /* 回调 */
    void (*release_cb)(struct video_frame *frame, void *userdata);
    void *cb_userdata;
} video_frame_t;
​
/**
 * @brief 视频帧池
 */
typedef struct video_frame_pool {
    video_frame_t *frames;                 /*!< 帧数组 */
    uint32_t pool_size;                    /*!< 池大小 */
    uint32_t free_count;                    /*!< 空闲帧数 */
    uint32_t *free_list;                    /*!< 空闲索引链表 */
    
    /* 帧属性模板 */
    uint32_t width;
    uint32_t height;
    pixel_format_t format;
    uint32_t frame_size;
    
    /* 内存管理器 */
    mem_manager_t *mmap_mgr;                /*!< 底层MMAP管理器 */
} video_frame_pool_t;
​
/**
 * @brief 视频内存管理器
 */
typedef struct mem_video_manager {
    mem_manager_t base;                      /*!< 基类 */
    
    /* 多个帧池(不同分辨率/格式)*/
    video_frame_pool_t *pools[MAX_FRAME_FORMATS];
    uint32_t pool_count;
    
    /* 活跃帧跟踪 */
    video_frame_t *active_frames[VIDEO_FRAME_POOL_SIZE * 2];
    uint32_t active_count;
    
    /* 底层管理器 */
    mem_manager_t *mmap_mgr;                  /*!< MMAP管理器 */
} mem_video_manager_t;
​
/**
 * @brief 创建视频内存管理器
 */
mem_manager_t* mem_video_create(void);
​
/**
 * @brief 创建视频帧池
 * @param mgr 视频管理器
 * @param width 帧宽度
 * @param height 帧高度
 * @param format 像素格式
 * @param pool_size 池大小
 * @return 0成功,-1失败
 */
int mem_video_create_pool(mem_manager_t *mgr, uint32_t width,
                           uint32_t height, pixel_format_t format,
                           uint32_t pool_size);
​
/**
 * @brief 从池中获取视频帧
 */
video_frame_t* mem_video_get_frame(mem_manager_t *mgr,
                                    uint32_t width, uint32_t height,
                                    pixel_format_t format);
​
/**
 * @brief 释放视频帧回池
 */
void mem_video_put_frame(video_frame_t *frame);
​
#endif /* MEM_VIDEO_H */
/**
 * @file mem_video.c
 * @brief 视频帧专用内存管理实现
 */
​
#include "mem_video.h"
#include "mem_mmap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
​
/* 私有操作函数 */
static void* video_alloc(void *mgr, uint32_t size, uint32_t align);
static void video_free(void *mgr, void *ptr);
static void video_dump(void *mgr);
static uint32_t video_get_used(void *mgr);
static uint32_t video_get_total(void *mgr);
​
static mem_ops_t video_ops = {
    .alloc = video_alloc,
    .free = video_free,
    .dump = video_dump,
    .get_used = video_get_used,
    .get_total = video_get_total
};
​
/**
 * @brief 计算视频帧大小
 */
static uint32_t calculate_frame_size(uint32_t width, uint32_t height,
                                      pixel_format_t format) {
    switch (format) {
        case PIX_FMT_NV12:
        case PIX_FMT_NV21:
            return width * height * 3 / 2;  /* Y + UV */
        case PIX_FMT_YUYV:
            return width * height * 2;
        case PIX_FMT_RGB24:
        case PIX_FMT_BGR24:
            return width * height * 3;
        case PIX_FMT_ARGB:
            return width * height * 4;
        default:
            return width * height * 3 / 2;  /* 默认YUV420 */
    }
}
​
/**
 * @brief 创建视频内存管理器
 */
mem_manager_t* mem_video_create(void) {
    mem_video_manager_t *mgr;
    
    mgr = (mem_video_manager_t*)calloc(1, sizeof(mem_video_manager_t));
    if (!mgr) return NULL;
    
    mgr->base.name = "Video Memory Manager";
    mgr->base.ops = &video_ops;
    mgr->base.private_data = mgr;
    
    /* 创建底层MMAP管理器 */
    mgr->mmap_mgr = mem_mmap_create();
    
    return (mem_manager_t*)mgr;
}
​
/**
 * @brief 创建视频帧池
 */
int mem_video_create_pool(mem_manager_t *base_mgr, uint32_t width,
                           uint32_t height, pixel_format_t format,
                           uint32_t pool_size) {
    mem_video_manager_t *mgr = (mem_video_manager_t*)base_mgr->private_data;
    video_frame_pool_t *pool;
    uint32_t frame_size;
    uint32_t total_size;
    uint8_t *mem;
    
    frame_size = calculate_frame_size(width, height, format);
    total_size = frame_size * pool_size;
    
    /* 预分配MMAP内存 */
    mem = (uint8_t*)mem_alloc(mgr->mmap_mgr, total_size);
    if (!mem) return -1;
    
    pool = (video_frame_pool_t*)calloc(1, sizeof(video_frame_pool_t));
    if (!pool) return -1;
    
    pool->frames = (video_frame_t*)calloc(pool_size, sizeof(video_frame_t));
    pool->free_list = (uint32_t*)calloc(pool_size, sizeof(uint32_t));
    pool->pool_size = pool_size;
    pool->free_count = pool_size;
    pool->width = width;
    pool->height = height;
    pool->format = format;
    pool->frame_size = frame_size;
    pool->mmap_mgr = mgr->mmap_mgr;
    
    /* 初始化帧数组 */
    for (uint32_t i = 0; i < pool_size; i++) {
        video_frame_t *frame = &pool->frames[i];
        uint8_t *frame_mem = mem + i * frame_size;
        
        frame->width = width;
        frame->height = height;
        frame->format = format;
        frame->stride = width;
        
        /* 设置平面指针(NV12格式)*/
        if (format == PIX_FMT_NV12 || format == PIX_FMT_NV21) {
            frame->y_plane = frame_mem;
            frame->uv_plane = frame_mem + width * height;
            frame->y_size = width * height;
            frame->uv_size = width * height / 2;
        } else {
            frame->y_plane = frame_mem;
            frame->y_size = frame_size;
        }
        
        frame->ref_count = 0;
        pool->free_list[i] = i;
    }
    
    mgr->pools[mgr->pool_count++] = pool;
    
    printf("Created video frame pool: %ux%u, format %d, %u frames, "
           "total %u bytes\n", width, height, format, pool_size, total_size);
    
    return 0;
}
​
/**
 * @brief 从池中获取视频帧
 */
video_frame_t* mem_video_get_frame(mem_manager_t *base_mgr,
                                    uint32_t width, uint32_t height,
                                    pixel_format_t format) {
    mem_video_manager_t *mgr = (mem_video_manager_t*)base_mgr->private_data;
    video_frame_pool_t *pool = NULL;
    uint32_t frame_index;
    video_frame_t *frame;
    
    /* 查找匹配的帧池 */
    for (uint32_t i = 0; i < mgr->pool_count; i++) {
        if (mgr->pools[i]->width == width &&
            mgr->pools[i]->height == height &&
            mgr->pools[i]->format == format) {
            pool = mgr->pools[i];
            break;
        }
    }
    
    if (!pool || pool->free_count == 0) {
        return NULL;
    }
    
    /* 从空闲列表获取索引 */
    frame_index = pool->free_list[--pool->free_count];
    frame = &pool->frames[frame_index];
    
    /* 初始化帧 */
    frame->timestamp = 0;
    frame->sequence = 0;
    frame->ref_count = 1;
    frame->release_cb = NULL;
    frame->cb_userdata = NULL;
    
    /* 添加到活跃列表 */
    mgr->active_frames[mgr->active_count++] = frame;
    
    return frame;
}
​
/**
 * @brief 释放视频帧回池
 */
void mem_video_put_frame(video_frame_t *frame) {
    mem_video_manager_t *mgr;  /* 需要从frame获取 */
    video_frame_pool_t *pool = NULL;
    
    if (!frame) return;
    
    frame->ref_count--;
    
    if (frame->ref_count > 0) return;
    
    /* 这里需要找到所属的pool,简化处理 */
    /* 实际应用中需要从frame反向找到pool */
    
    if (frame->release_cb) {
        frame->release_cb(frame, frame->cb_userdata);
    }
    
    /* 重置帧 */
    memset(frame->y_plane, 0, frame->y_size);
    if (frame->uv_plane) {
        memset(frame->uv_plane, 0, frame->uv_size);
    }
}
​
/**
 * @brief 视频内存分配(通用接口)
 */
static void* video_alloc(void *mgr_priv, uint32_t size, uint32_t align) {
    mem_video_manager_t *mgr = (mem_video_manager_t*)mgr_priv;
    
    /* 对于非视频帧的小内存,转发给MMAP管理器 */
    return mem_alloc(mgr->mmap_mgr, size);
}
​
/**
 * @brief 视频内存释放
 */
static void video_free(void *mgr_priv, void *ptr) {
    mem_video_manager_t *mgr = (mem_video_manager_t*)mgr_priv;
    
    mem_free(mgr->mmap_mgr, ptr);
}
​
/**
 * @brief 打印管理器状态
 */
static void video_dump(void *mgr_priv) {
    mem_video_manager_t *mgr = (mem_video_manager_t*)mgr_priv;
    
    printf("\n=== Video Memory Manager Dump ===\n");
    printf("Pool count: %u\n", mgr->pool_count);
    printf("Active frames: %u\n", mgr->active_count);
    
    for (uint32_t i = 0; i < mgr->pool_count; i++) {
        video_frame_pool_t *pool = mgr->pools[i];
        printf("  Pool %u: %ux%u format %d, %u/%u free\n",
               i, pool->width, pool->height, pool->format,
               pool->free_count, pool->pool_size);
    }
}

六、测试程序

/**
 * @file test_memory.c
 * @brief 内存管理测试程序
 * @details 测试各种内存管理器的功能
 */
​
#include "mem_pool.h"
#include "mem_mmap.h"
#include "mem_video.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
​
/**
 * @brief 测试小内存池
 */
void test_mem_pool(void) {
    printf("\n=== Testing Memory Pool ===\n");
    
    /* 创建256KB内存池 */
    mem_manager_t *pool = mem_pool_create(256 * 1024);
    if (!pool) {
        printf("Failed to create memory pool\n");
        return;
    }
    
    /* 分配各种大小的内存 */
    void *ptr1 = MEM_ALLOC(pool, 32);
    void *ptr2 = MEM_ALLOC(pool, 64);
    void *ptr3 = MEM_ALLOC(pool, 128);
    void *ptr4 = MEM_ALLOC(pool, 256);
    
    printf("Allocated: %p(32), %p(64), %p(128), %p(256)\n",
           ptr1, ptr2, ptr3, ptr4);
    
    /* 写入测试数据 */
    if (ptr1) strcpy((char*)ptr1, "Memory Pool Test");
    if (ptr2) memset(ptr2, 0xAA, 64);
    if (ptr3) memset(ptr3, 0xBB, 128);
    
    /* 释放 */
    MEM_FREE(pool, ptr1);
    MEM_FREE(pool, ptr2);
    MEM_FREE(pool, ptr3);
    MEM_FREE(pool, ptr4);
    
    pool->ops->dump(pool->private_data);
    
    mem_pool_destroy(pool);
}
​
/**
 * @brief 测试MMAP大块内存
 */
void test_mem_mmap(void) {
    printf("\n=== Testing MMAP Memory ===\n");
    
    mem_manager_t *mmap_mgr = mem_mmap_create();
    if (!mmap_mgr) {
        printf("Failed to create MMAP manager\n");
        return;
    }
    
    /* 分配大块内存 */
    void *buf1 = MEM_ALLOC(mmap_mgr, 2 * 1024 * 1024);  /* 2MB */
    void *buf2 = MEM_ALLOC(mmap_mgr, 4 * 1024 * 1024);  /* 4MB */
    void *buf3 = MEM_ALLOC(mmap_mgr, 1 * 1024 * 1024);  /* 1MB */
    
    printf("Allocated: %p(2MB), %p(4MB), %p(1MB)\n", buf1, buf2, buf3);
    
    /* 写入数据 */
    if (buf1) memset(buf1, 0x11, 2 * 1024 * 1024);
    if (buf2) memset(buf2, 0x22, 4 * 1024 * 1024);
    
    /* 释放 */
    MEM_FREE(mmap_mgr, buf1);
    MEM_FREE(mmap_mgr, buf2);
    MEM_FREE(mmap_mgr, buf3);
    
    mmap_mgr->ops->dump(mmap_mgr->private_data);
    
    mem_mmap_destroy(mmap_mgr);
}
​
/**
 * @brief 测试视频帧管理
 */
void test_video_frames(void) {
    printf("\n=== Testing Video Frame Management ===\n");
    
    mem_manager_t *video_mgr = mem_video_create();
    if (!video_mgr) {
        printf("Failed to create video manager\n");
        return;
    }
    
    /* 创建1080p帧池 */
    mem_video_create_pool(video_mgr, 1920, 1080, PIX_FMT_NV12, 4);
    
    /* 创建720p帧池 */
    mem_video_create_pool(video_mgr, 1280, 720, PIX_FMT_NV12, 8);
    
    /* 获取视频帧 */
    video_frame_t *frame1 = mem_video_get_frame(video_mgr, 
                                                 1920, 1080, PIX_FMT_NV12);
    video_frame_t *frame2 = mem_video_get_frame(video_mgr,
                                                 1280, 720, PIX_FMT_NV12);
    video_frame_t *frame3 = mem_video_get_frame(video_mgr,
                                                 1920, 1080, PIX_FMT_NV12);
    
    if (frame1) {
        frame1->timestamp = 1000;
        frame1->sequence = 1;
        printf("Got frame1: %ux%u, ts=%llu\n",
               frame1->width, frame1->height, 
               (unsigned long long)frame1->timestamp);
    }
    
    /* 模拟使用帧 */
    sleep(1);
    
    /* 释放帧 */
    if (frame1) mem_video_put_frame(frame1);
    if (frame2) mem_video_put_frame(frame2);
    if (frame3) mem_video_put_frame(frame3);
    
    video_mgr->ops->dump(video_mgr->private_data);
    
    /* 这里需要添加销毁函数 */
    /* mem_video_destroy(video_mgr); */
}
​
/**
 * @brief 主函数
 */
int main(void) {
    printf("Memory Management System Test\n");
    printf("============================\n");
    
    test_mem_pool();
    test_mem_mmap();
    test_video_frames();
    
    printf("\nAll tests completed.\n");
    return 0;
}

七、Makefile

# Makefile for Memory Manager
CC = gcc
CFLAGS = -Wall -Wextra -g -I./include
LDFLAGS = -lpthread
​
SRCDIR = src
INCDIR = include
TESTDIR = test
​
SOURCES = $(SRCDIR)/mem_core.c \
          $(SRCDIR)/mem_pool.c \
          $(SRCDIR)/mem_mmap.c \
          $(SRCDIR)/mem_video.c
​
OBJECTS = $(SOURCES:.c=.o)
TEST_TARGET = test_memory
​
all: $(TEST_TARGET)
​
$(TEST_TARGET): $(OBJECTS) $(TESTDIR)/test_memory.c
    $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
​
%.o: %.c
    $(CC) $(CFLAGS) -c $< -o $@
​
clean:
    rm -f $(OBJECTS) $(TEST_TARGET)
​
run: $(TEST_TARGET)
    ./$(TEST_TARGET)
​
.PHONY: all clean run

八、设计思想总结

  1. 树形结构设计

    • mem_manager_t 作为基类

    • 各具体管理器继承基类

    • 视频管理器包含多个帧池

  2. 内存管理策略

    • 小内存:内存池预分配,避免碎片

    • 大内存:MMAP管理,支持大块连续内存

    • 视频帧:专用管理器,支持引用计数

  3. 统一接口

    • 所有管理器实现相同的 mem_ops_t

    • 支持调试信息(文件、行号)

    • 统一的内存头部管理

  4. 视频优化

    • 帧池化,避免频繁分配

    • 支持多种像素格式

    • 引用计数管理生命周期

更多推荐