FreeRTOS代码阅读笔记:heap_4.c

本文是关于FreeRTOS中heap_4.c内存管理策略的笔记,该策略与heap_2.c类似,但增加了空闲内存块的合并功能,通过按内存起始地址排序来优化内存分配。主要讨论了链表初始化、空闲块插入以及如何减少内存碎片。
摘要由CSDN通过智能技术生成

FreeRTOS中对于内存的管理当前一共有5种实现方式(作者当前的版本是10.1.1),均在【 \Source\portable\MemMang 】下面,这里笔记下。

heap_4.c和第二种方式比较相似,只不过增加了一个和并算法,将相邻空闲内存合并为一个大内存,和方法一、二管理策略一样,内存堆仍为一个大数组。

区别在于第四种内存管理策略的空闲块链表不是以内存块大小为存储顺序,而是以内存块起始地址大小为存储顺序,地址小的在前,地址大的在后。这也是为了适应合并算法而作的改变。

使用方法:
头文件:FreeRTOSConfig.h 
配置参数:
configTOTAL_HEAP_SIZE             定义系统所用的堆栈大小。
configUSE_MALLOC_FAILED_HOOK      默认0: 1则开启钩子函数,内存分配失败则调用 
 
函数调用:	
      vPortInitialiseBlocks();//初始化
      ptr=pvPortMalloc(1024);
	  if(ptr !=NULL)
	  {
	  freemem=xPortGetFreeHeapSize(); 
	  printf("剩余内存 %d \r\n",i,freemem); 
	  }
	  else
	  {
	  printf("获取内存失败\r\n");break;

重要参数:

重要的参数备注:
(1)FreeRTOS  内存堆为:ucHeap[] 大小为 configTOTAL_HEAP_SIZE 
(2)pucAlignedHeap 作为堆栈字节对齐后的起始地址(怎么实现的思考一下)
(3)xTotalHeapSize 表示堆栈进行内存大小减去被舍弃字节后的总内存大小
(4)xStart, xEnd; 记录空闲链表的首尾。
(5)pxFirstFreeBlock 空闲链表
(6)xMinimumEverFreeBytesRemaining 是一个统计值,存储了当前模拟堆运行时的最小剩余内存容量
(7)xFreeBytesRemaining:当前模拟堆的剩余内存容量

举个例子:
内存申请:
空闲链是按照地址排序的,从链表中找出内存大小满足的内存块。相对于方式二其查询时间可能变长了。
内存释放:
释放内存后会比较前后的空闲块是否地址连接,是则内存合并。

heap_2.c分析:

将源码解析调整一下顺序:

下面是链表的初始化,heap_2.c中链表的尾部数据并未保存在链表内,是以变量的形式存在的。heap_4.c中的链表尾部数据结构保存在链表空间尾部。

下面是链表初始化代码:

//关于堆栈的初始化
//第一步:起始地址做字节对齐  保存pucAlignedHeap 可用空间大小为xTotalHeapSize 
//第二步:计算首尾 ,这里需要注意的是链表的尾部指针是保存到该地址尾部的
//第三部:完成链表的初始化,记录内存块信息

static void prvHeapInit( void )
{
BlockLink_t *pxFirstFreeBlock;
uint8_t *pucAlignedHeap;
size_t uxAddress;
size_t xTotalHeapSize = configTOTAL_HEAP_SIZE;

	/* Ensure the heap starts on a correctly aligned boundary. */
	//起始地址做字节对齐处理
	uxAddress = ( size_t ) ucHeap;
	if( ( uxAddress & portBYTE_ALIGNMENT_MASK ) != 0 )
	{
		uxAddress += ( portBYTE_ALIGNMENT - 1 );
		uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
		xTotalHeapSize -= uxAddress - ( size_t ) ucHeap;  //减去对齐舍弃的字节
	}

	pucAlignedHeap = ( uint8_t * ) uxAddress;         //对齐后可以用的起始地址

	/* xStart is used to hold a pointer to the first item in the list of free
	blocks.  The void cast is used to prevent compiler warnings. */
	//xStart链表的头 
	xStart.pxNextFreeBlock = ( void * ) pucAlignedHeap; 
	xStart.xBlockSize = ( size_t ) 0;

	/* pxEnd is used to mark the end of the list of free blocks and is inserted
	at the end of the heap space. */
	//pxEnd链表的尾
	uxAddress = ( ( size_t ) pucAlignedHeap ) + xTotalHeapSize;
	uxAddress -= xHeapStructSize;
	uxAddress &= ~( ( size_t ) portBYTE_ALIGNMENT_MASK );
	pxEnd = ( void * ) uxAddress;                       
	pxEnd->xBlockSize = 0;
	pxEnd->pxNextFreeBlock = NULL;

	/* To start with there is a single free block that is sized to take up the
	entire heap space, minus the space taken by pxEnd. */
	//开始时候将内存堆整个看作为一个空闲内存块
	pxFirstFreeBlock = ( void * ) pucAlignedHeap;
	pxFirstFreeBlock->xBlockSize = uxAddress - ( size_t ) pxFirstFreeBlock;
	pxFirstFreeBlock->pxNextFreeBlock = pxEnd;

	/* Only one block exists - and it covers the entire usable heap space. */
	xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; //记录最小的空闲内存块大小
	xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize;            //剩余内存堆大小

	/* Work out the position of the top bit in a size_t variable. */
	xBlockAllocatedBit = ( 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值