基于freertos的嵌入式系统开发(三)FreeRTOS的内存管理方法1

33 篇文章 2 订阅
8 篇文章 1 订阅

基于freertos的嵌入式系统开发(三)FreeRTOS的内存管理方法1

简介

我们知道c语言中,内存的申请和释放对应于C的库函数malloc和free。malloc函数一个形参,通常是这么使用的:

        int* p = (int*)malloc(size(int)); //申请一段为int大小的内存空间。

free函数:

      free(p);     //使用完之后应及时释放掉,防止内存泄漏。

在FreeRTOS中内存管理的接口函数为:pvPortMalloc、vPortFree,对应malloc和free,在源码中默认提供了5个文件,以最新版本\FreeRTOSv202112.00为例,该文件位于:

  \FreeRTOSv202112.00\FreeRTOSv202112.00\FreeRTOS\Source\portable\MemMang

目录下,见下图:

在这里插入图片描述
5个文件对应内存管理的5种方法,主要特征见下表:

在这里插入图片描述
下面结合源码分析,对这5钟方式逐一进行分析

方式1:Heap_1.c

方式1实现了非常基础的 pvPortMalloc,没有实现 vPortFree,从来不销毁任务、或者其他内核对象,适用于资源有限、需求明确的小型专用嵌入式系统,在调度器运行之前,系统需要的 tasks 和其他内核对象已经确定并创建完毕,并且已分配的内存会保持分配状态,直到程序结束。这样就不需要考虑复杂的内存动态分配、内存泄露和碎片化问题,重点关注代码简洁、可靠等。

内存分配函数 void * pvPortMalloc( size_t xWantedSize )

最新版本\FreeRTOSv202112.00的内核版本为FreeRTOS Kernel V10.4.6,内存分配函数的的工作流程如下图:

在这里插入图片描述
下面看Heap_1.c的代码:

void * pvPortMalloc( size_t xWantedSize )
{
  void * pvReturn = NULL;
  static uint8_t * pucAlignedHeap = NULL;

/* Ensure that blocks are always aligned. 字节对齐处理 */
#if ( portBYTE_ALIGNMENT != 1 )
    {
        if( xWantedSize & portBYTE_ALIGNMENT_MASK )
        {
            /* Byte alignment required. Check for overflow. */
            if ( (xWantedSize + ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) )) > xWantedSize )
            {
                xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
            }
            else
            {
                xWantedSize = 0;
            }
        }
    }
#endif

vTaskSuspendAll();   //挂起所以任务
{
    if( pucAlignedHeap == NULL )  /* 释放字节对齐? */
    {
        /* Ensure the heap starts on a correctly aligned boundary 确保内存堆的开始地址是字节对齐的 */.
        pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) & ucHeap[ portBYTE_ALIGNMENT - 1 ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
    }

    /* Check there is enough room left for the allocation and.
     检查是否有足够的内存供分配,以及是否越界  */
    if( ( xWantedSize > 0 ) && /* valid size */
        ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
        ( ( xNextFreeByte + xWantedSize ) > xNextFreeByte ) ) /* Check for overflow. */
    {
        /* Return the next free byte then increment the index past this
         * block. */
        pvReturn = pucAlignedHeap + xNextFreeByte; //生成新分配内存地址放到返回值
        xNextFreeByte += xWantedSize; //未分配内存指针后移。
    }
    traceMALLOC( pvReturn, xWantedSize );
}
( void ) xTaskResumeAll();/* 分配后,恢复所有任务 */

/* 如果分配失败且定义了hook函数,则调用hook函数 */
#if ( configUSE_MALLOC_FAILED_HOOK == 1 )  
    {   
        if( pvReturn == NULL )
        {
            extern void vApplicationMallocFailedHook( void );
            vApplicationMallocFailedHook();
        }
    }
#endif

return pvReturn;

}

内存释放函数 void vPortFree( void * pv )

前面讲过,方式1的内存分配方式并不会释放内存,所以,该函数只是做一个invalid的assert,并没有任务释放内存操作,代码如下:

 void vPortFree( void * pv )
{
/* Memory cannot be freed using this scheme.  See heap_2.c, heap_3.c and
 * heap_4.c for alternative implementations, and the memory management pages of
 * https://www.FreeRTOS.org for more information. */
( void ) pv;

/* Force an assert as it is invalid to call this function. */
configASSERT( pv == NULL );

}

FreeRTOS中的断言函数configASSERT()和标准C中的断言函数assert()是一样的。

初始化 void vPortInitialiseBlocks( void )

只有在清除静态内存时需要调用,基本用不着,代码如下:

void vPortInitialiseBlocks( void )
{
	 /* Only required when static memory is not cleared. */
	xNextFreeByte = ( size_t ) 0;
}

获取自由Heap大小 size_t xPortGetFreeHeapSize( void )

该函数可以获取可供分配的自由heap大小,可以作为下一次分配前的参考,防止出现内存申请失败的情况,当然,申请失败处理也可以在钩子函数vApplicationMallocFailedHook来处理。
代码如下:

	size_t xPortGetFreeHeapSize( void )
	{
  	return( configADJUSTED_HEAP_SIZE - xNextFreeByte );
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cyjbj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值