FreeRTOS Heap4内存管理分析

本文详细介绍了FreeRTOS的Heap4内存管理机制,包括内存的划分、数据结构、初始化、内存分配和释放过程,强调了内存对齐和哨兵空间的重要性。
摘要由CSDN通过智能技术生成

一. 简要介绍

    Heap4 内存管理是一种基于链表形式的管理方式。它将整个内存空间划分成三块空间,分别是可供分配的空间,结束哨兵空间,舍弃掉的空间。可供分配的空间显而易见,每次用户调用 malloc 函数就是从这块空间划分的。结束哨兵的作用也是为检测分配时是否已经超出了可分配空间地址范围,避免越界。舍弃的空间是因为需要内存对齐的原因不得不舍弃掉的一小部分内存。举个例子:假如我需要分配的内存地址以 8 字节对齐也就是说分配出去的地址必须能够被 8 整除,同时每次分配最少为8个字节。这时整块内存空间以 0x68 0001 开始  ,总共 24个字节的空间。那么为了分配满足 8 字节对齐显然 0x6800 0001~ 0x6800 0007) 号的地址就不得不舍弃,实际可用是从 0x6800 0008开始。结尾的多出的字节也去掉。末尾的 从0x6800 0024 只剩一个字节不满足最低字节数分配要求也得舍弃。

二. 重要数据结构说明

    typedef struct A_BLOCK_LINK
    {
        struct A_BLOCK_LINK* pxNextFreeBlock;        /*<< The next free block in the list. */
        size_t xBlockSize;                                            /*<< The size of the free block. */

    } BlockLink_t;

    这个结构体两个内容,pxNextFreeBlock 指向链表下一个 Block 。xBlockSize 指这个Block记录着后面有多少个字节可用。实际上哨兵空间就是在可用空间的末尾的8个字节存一个BlockLink_t 结构体。使它的pxNextFreeBlock指向 NULL ,size为零。程序以 xStart 全局变量保存的第一个 BlockLink,然后一个串一个,直到最后的结束哨兵,程序以 pxEnd 指向这个地址。

三. 内存初始化

    在初始化过程中,第一步就需要掐头去尾,去掉不满足分配要求的地址空间。第二步用一个 xStart 全局变量保存可用的首地址。所以应尽量是需要管理的地址首地址满足8字节对齐的要求,减少内存浪费。在xStart 保存的地址上放一个 BlockLink_t 结构体,占用 8个字节,用来存放 结束哨兵的地址和整个可用的字节数。第三步用 pxEnd 保存末尾的哨兵地址。整个初始化工作完成以后,我们用两个全局变量分别保存的整个空间的开始于结尾,在地址开始的前 8 个字节保存着末尾的地址和整个后面可用字节的数量 size,可用地址空间的前8个控制字节和后面的size 个可分配的字节构成了内存分配的基本单元。哨兵空间也可认为是特殊的单元,只是他后面跟着的可用于分配的字节数为零。

四. 内存分配

     刚开始程序只有一个可用于分配的单元,xStart 保存着这个地址,从而得到可分配的字节数。如果需要分配的字节小于xStart可分配的字节数,那么就从可分配的字节数中切出前面一部分。原本的基本单元就形成了两个新的基本单元。分配出去的基本单元a 和 剩下的基本单元b 。 修改 a 的前八个字节,也就是 BlockLink_t 保存的控制信息,使它的长度是实际分配的字节数。注意当需要分配的字节不能被8 整除的将会自动扩充以满足这个要求。所以说是实际分配的字节数。使它的pxNextFreeBlock 指向 NULL 。将基本单元 a 的第 8 个字节的地址返回给申请的用户。这样完成了整个分配工作的一半。接下来需要修改基本单元b中的前8个字节 BlockLink_t 中的控制信息,xBlockSize等于剩下的字节数。然后根据基本单元b的地址从按照小到大的顺序插入到空闲链表中。整个插入过程有个合并过程需要注意,当插入空间的地址正好挨着上一个空闲块的末尾将会合并这两个块。接着判断插入空间的地址的末尾是否挨着下一个空闲的块,也将合并这连个块。

五. 内存释放

    内存释放工作完全可用参考内存分配的第二部分工作,将剩下的块插入到链表的合适的位置。

六 代码讲解


#include <stdlib.h>
#include <stdint.h>

/* Block sizes must not get too small. */
#define heapMINIMUM_BLOCK_SIZE	( ( size_t ) ( xHeapStructSize << 1 ) )

/* Assumes 8bit bytes! */
#define heapBITS_PER_BYTE		( ( size_t ) 8 )

#define portBYTE_ALIGNMENT			8
#define portBYTE_ALIGNMENT_MASK ( 0x0007 )

#define configTOTAL_HEAP_SIZE ((size_t)(1000000)) // 1000000
static unsigned char ucHeap[configTOTAL_HEAP_SIZE] __attribute__ ( ( at ( 0X68000000 ) ) );

/* Define the linked list structure.  This is used to link free blocks in order
of
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值