FreeRtos内存管理--外部缓冲区释放到内存堆中

本文探讨了FreeRTOS中外部缓冲区如何通过vPortFree接口加入内存管理链表,并通过pvPortMalloc申请空间。讨论了不同地址情况下外部缓冲区的插入位置及可能的问题。

在学习FreeRtos的内存管理过程中,发现了一个有趣的现象。通过调用vPortFree接口释放一个外部缓冲区,内存管理也会把外部缓冲区挂载到内存管理的链表上,之后通过pvPortMalloc接口,可以从外部缓冲区上申请和释放空间。外部缓冲区释放到内存管理的链表上,有以下两种情况(读者技术水平有限,不确定是否有其他情况):
一、外部缓冲区的地址小于内存管理的堆地址

此时通过vPortFree接口释放外部缓冲区,外部缓冲区会被挂载到链表最前面(链表头xStart指向的下一个地址)。

修改的代码如下,外部缓冲区申明,堆空间地址设置为决定地址,保证外部缓冲区的地址小于堆空间地址:

  static uint8_t sbuf1[108];  // 定义的外部缓冲区1
  static uint8_t sbuf2[208];  // 定义的外部缓冲区2

  // 内存管理的堆空间,使用绝对地址保证外部缓冲区地址在堆空间前面
  static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] @0x20002800;

测试的函数接口,在任务中调用:

// 内存管理测试函数,在任务中调用进行测试
void heap_test(void)
{
  static uint8_t* buf1, *buf2;
  BlockLink_t *pxLink;

  buf1 = pvPortMalloc(10);
  
  pxLink = (BlockLink_t *)sbuf1;
  pxLink->pxNextFreeBlock = NULL;
  pxLink->xBlockSize = xBlockAllocatedBit|100;
  vPortFree(&sbuf1[8]); // 释放外部缓冲区sbuf1到内存管理的链表上
  
  pxLink = (BlockLink_t *)sbuf2;
  pxLink->pxNextFreeBlock = NULL;
  pxLink->xBlockSize = xBlockAllocatedBit|200;
  vPortFree(&sbuf2[8]); // 释放外部缓冲区sbuf2到内存管理的链表上

  buf2 = pvPortMalloc(10);  // 申请空间,由于sbuf2挂载在链表最前面,
                            // 申请的空间是sbuf2的空间
  vPortFree(buf2);
  vPortFree(buf1);
}

以下是外部缓冲区释放(调用vPortFree接口)到内存管理,和申请内存的过程(调用pvPortMalloc接口)。

① 外部缓冲区释放到内存管理链表前:

② 外部缓冲区1释放到内存管理链表:

③ 外部缓冲区2释放到内存管理链表:

④ 内存管理申请到外部缓冲区的空间:

⑤ 申请到的外部缓冲区空间重新释放:

二、外部缓冲区的地址大于内存管理的堆地址

修改的代码如下,外部缓冲区申明,堆空间地址设置为决定地址,保证外部缓冲区的地址大于堆空间地址:

  static uint8_t sbuf1[108];  // 定义的外部缓冲区1
  static uint8_t sbuf2[208];  // 定义的外部缓冲区2

  // 内存管理的堆空间,使用绝对地址保证外部缓冲区地址在堆空间后面
  static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ] @0x20000000;

把外部缓冲区释放到内存管理的链表时,需要获取释放的内存块需要插入的链表位置(链表结点排序规则是根据指向的内存块地址由小到大排序),因为外部缓冲区地址大于堆空间地址,所有会遍历到链表的尾部,链表的尾部pxEnd的下一个内存块地址指针指向NULL,会导致不可控的溢出发生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值