(五)内存管理

RT-thread中的头部主要信息如下

struct heap_mem
{
    /* magic and used flag */
    uint16_t magic;  
    uint16_t used;

    uint32_t next, prev;

};

初始化动态内存

在使用动态分配之前需要先初始化一块内存, 接收两个参数, begin_addr为内存起始地址, end_addr为内存终止地址.

void pt_system_heap_init(void *begin_addr, void *end_addr);
// 示例用法
    // 静态定义一块内存, 大小为HEAP_SIZE字节
    static uint8_t heap_mem[HEAP_SIZE];   
    // 将这块内存的首尾地址作为pt_system_heap_init的参数
    pt_system_heap_init(&heap_mem[0], &heap_mem[HEAP_SIZE - 1]); 

对一块用于动态分配的内存初始化后如下所示
(五)内存管理

输入的参数begin_addr和end_addr可能未对齐到4字节, 因此实际使用的内存块可能比定义的要小一些.
lfree指向当前空闲可以分配的内存地址.

malloc分配内存

malloc函数在这一大块内存中寻找可用的内存, 检查头部used变量, 该块内存是否被占用, 距离下一块内存的空间是否足够等, 若都满足, 则分配使用. 下图是分配一块内存后的示意图.
(五)内存管理
成功分配一块内存后, 在其后边写入一个信息头, 并将前后内存块的next prev正确设置, lfree也指向了新的空闲内存块.

free释放内存

free函数将释放一块内存, 只是将used标记为0, 表示这块内存不再使用, 但是其内存内容不会清除.
(五)内存管理

为了避免越分配内存越碎片化, 在free中还检查前后的内存块是不是空闲的, 如果是空闲的则把他们合并起来形成一块大内存, 图中灰色的区域就合并到前一块内存中了.
(五)内存管理

realloc调整内存大小

realloc调整内存大小分为调大和调小.
对于调大的情况, 必须另外分配一块内存, 并将原来内存的数据拷贝到新分配的内存中, 然后释放掉旧内存.
(五)内存管理
对于调小的情况, 无需另外分配一块内存, 只需在原来的内存上分割即可.
(五)内存管理

上一篇:堆排序思想及代码实现


下一篇:堆 heap