heap_4内存管理

一、基础

1、静态大数组用于分配内存

cpp 复制代码
static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];//编译期的静态数组,用于分配

2、块头链表

cpp 复制代码
typedef struct A_BLOCK_LINK
{
	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<<下一块空闲内容*/
	size_t xBlockSize;						/*<<当前空闲块大小,最高位表示是否分配*/
} BlockLink_t;

3、头尾哨兵

cpp 复制代码
static BlockLink_t xStart;   /* 链表头(地址最小,xBlockSize=0) */
static BlockLink_t *pxEnd;   /* 链表尾(地址最大,标记"没有更多块了") */

头哨兵:作为查找起始

尾哨兵:作为查找结束

二、prvHeapInit

1、从堆内存起点进行八字节对齐

2、初始化头哨兵,指向对对齐后的起点,大小为0

cpp 复制代码
xStart.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 字节(xBlockSize=0, pxNextFreeBlock=NULL)
├─────────────┤
│ 尾部余量     │ 0~7 字节(pxEnd 对齐后剩下的,不可用)
└─────────────┘ 0x20000100 + 3072(数组末尾)

三、void *pvPortMalloc( size_t xWantedSize )

首先暂停任务调度,第一次调用时若没有初始化则进行初始化,将申请大小加上8字节块头,若剩余总空间大于总需要空间,则从头哨兵开始找第一个符合大小的内存块,内存块大小包含8字节块头和申请的内存大小。然后记录块的返回地址,把这块地方从空闲链表里摘除,将后续剩余空间作为一个新的空闲块放入空闲块链表,更新统计值,恢复任务调度。返回地址。

四、void vPortFree( void *pv )

首先往前8个地址找到块头,校验是否可以释放,可以的话就清楚标志位(最高位),然后挂起调度器,把空闲块大小加进总空闲数,调用prvInsertBlockIntoFreeList将该块插回空闲链表,prvInsertBlockIntoFreeList里的操作是首先从头哨兵开始找到该空闲块,判断前后是否也为空闲块,若是则合并,合并就是改大小字段和跳指针,然后链接进空闲块链表。

相关推荐
starzy19907 小时前
深入理解Scala隐式类:扩展方法机制
开发语言·人工智能·scala
Pniubi7 小时前
怎么排查慢SQL,怎么解决?
java·数据库·sql
M--Y8 小时前
LangGraph 工作流模式
开发语言·javascript·python·langchain·大模型·llm·langgraph
薛之谦_8 小时前
Java 全栈知识体系:从 IDEA 高效开发到 JVM、并发与 Stream 实战
java·jvm·intellij-idea
forest_099 小时前
多 Agent 协作第二课:交叉验证≠独立验证
人工智能·python·算法·机器学习·prompt·agi
吴可可1239 小时前
WScript Shell操作注册表详解
开发语言
纪念 22910 小时前
C++ 算法基础 (差分)
开发语言·c++·算法
文丑颜不良啊12 小时前
LeetCode2761~2780题目解析
java·leetcode
jyOverQ13 小时前
从零学 JVM(六):垃圾回收算法详解——标记清除、标记复制与标记整理
jvm·算法
IT枫斗者枫哥13 小时前
子线程断言失败,JUnit 为什么还显示通过?
java·后端