FreeRTOS代码剖析之3:内存管理Heap_3.c

    FreeRTOS8.0.1的第三个模型Heap_3,可以说是最容易理解的一个内存堆管理模型。因为在这个模型里,FreeRTOS直接将标准C库中的malloc()和free()进行加工打包。 (Implementation of pvPortMalloc() and vPortFree() that relies on the compilers own malloc() and free() implementations.)因此,FreeRTOSConfig.h中的configTOTAL_HEAP_SIZE在这个模型中就失效了。FreeRTOS直接管理编译器编译时分配的堆。例如,在STM32F103中,FreeRTOS管理的堆就定义在启动文件startup_stm32f10x_xd.s中。
    不过,就算是直接引用了标准C库中的malloc()和free()也是不行的。原因是库中的这两个接口在FreeRTOS中并不是线程安全的。因此,FreeRTOS将这两个接口进行重新打包。首先看看pvPortMalloc()是怎么将malloc()重新打包的。

void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn;

 vTaskSuspendAll();
 {
  pvReturn = malloc( xWantedSize );
  traceMALLOC( pvReturn, xWantedSize );
 }
 ( void ) xTaskResumeAll();

 #if( configUSE_MALLOC_FAILED_HOOK == 1 )
 {
  if( pvReturn == NULL )
  {
   extern void vApplicationMallocFailedHook( void );
   vApplicationMallocFailedHook();
  }
 }
 #endif

 return pvReturn;
}

    这一段就是pvPortMalloc()的所有代码,很短,也很容易理解。首先,和Heap_1、Heap_2一样,用vTaskSuspendAll()挂起所有的任务,以确保分配内存的过程是线程安全的。接下来才使用malloc()进行内存分配。然后就是调用调试信息宏traceMALLOC()并调用xTaskResumeAll()恢复被挂起的任务。这样基本的分配内存流程就结束了。如果在FreeRTOS.h中设置了勾子函数宏,则在调用勾子函数vApplicationMallocFailedHook()之后再向用户返回分配内存的首地址。

void vPortFree( void *pv )
{
 if( pv )
 {
  vTaskSuspendAll();
  {
   free( pv );
   traceFREE( pv, 0 );
  }
  ( void ) xTaskResumeAll();
 }
}

    上面这一段代码是vPortFree()对free()的重新包装。过程也是很简单。首先是检查指针的有效性,然后挂起所有任务,调用free()接口将内存回收,接着调用调试信息宏traceFREE(),最后恢复所有挂起进程。这样整个回收过程就结束了。

总结:一开始的时候看到原有的注释说明,就不想为这个模型剖析下去了。不过后来想想,要成大事必从小事做起,就算是简单也不能放弃,所以还是把这一部分的代码剖析了。以后不能再有这种懒惰的想法了。FreeRTOS中4个内存堆管理模型已经剖析完3个了,还有1个下次继续剖析。之后应该能进入内核了吧?→_→

你可能感兴趣的:(嵌入式)