ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

heap_4内存管理

heap_4内存管理 一、基础1、静态大数组用于分配内存static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];//编译期的静态数组用于分配2、块头链表typedef struct A_BLOCK_LINK { struct A_BLOCK_LINK *pxNextFreeBlock; /*下一块空闲内容*/ size_t xBlockSize; /*当前空闲块大小最高位表示是否分配*/ } BlockLink_t;3、头尾哨兵static BlockLink_t xStart; /* 链表头地址最小xBlockSize0 */ static BlockLink_t *pxEnd; /* 链表尾地址最大标记没有更多块了 */头哨兵作为查找起始尾哨兵作为查找结束二、prvHeapInit1、从堆内存起点进行八字节对齐2、初始化头哨兵指向对对齐后的起点大小为0xStart.pxNextFreeBlock ( void * ) pucAlignedHeap; /* 链表第一项 对齐后的起点 */ xStart.xBlockSize ( size_t ) 0; /* 哨兵自身大小为 0 */3、初始化尾哨兵从堆内存尾部往前8个字节再向下对齐4、初始化唯一空闲块也就是第一个空闲块大小为可用堆-尾哨兵开销指向尾哨兵初始化后的ucHeap布局头哨兵不在这块内存但指向第一个空闲内存块ucHeap 数组3072B内部 ┌─────────────┐ 0x20000100数组首地址可能未对齐 │ 对齐损失 │ 0~7 字节不可用prvHeapInit 里扣掉了 ├─────────────┤ ← pucAlignedHeap对齐后的堆起点 │ 块头 BlockLink_t │ 8 字节 │ ├ pxNextFreeBlock → 指向 pxEnd ← 这就是指向尾哨兵的字段 │ └ xBlockSize → 整个块的大小含块头 ├─────────────┤ │ 空闲内容区 │ ← 真正能 malloc 出去的字节当前整块都是空闲的 │ 约 3056B │ ├─────────────┤ ← pxEnd 地址 起点 总大小 - 8向下对齐 │ pxEnd 哨兵 │ 8 字节xBlockSize0, pxNextFreeBlockNULL ├─────────────┤ │ 尾部余量 │ 0~7 字节pxEnd 对齐后剩下的不可用 └─────────────┘ 0x20000100 3072数组末尾三、void *pvPortMalloc( size_t xWantedSize )首先暂停任务调度第一次调用时若没有初始化则进行初始化将申请大小加上8字节块头若剩余总空间大于总需要空间则从头哨兵开始找第一个符合大小的内存块内存块大小包含8字节块头和申请的内存大小。然后记录块的返回地址把这块地方从空闲链表里摘除将后续剩余空间作为一个新的空闲块放入空闲块链表更新统计值恢复任务调度。返回地址。四、void vPortFree( void *pv )首先往前8个地址找到块头校验是否可以释放可以的话就清楚标志位最高位然后挂起调度器把空闲块大小加进总空闲数调用prvInsertBlockIntoFreeList将该块插回空闲链表prvInsertBlockIntoFreeList里的操作是首先从头哨兵开始找到该空闲块判断前后是否也为空闲块若是则合并合并就是改大小字段和跳指针然后链接进空闲块链表。
返回列表