FreeRTOS中对于内存的管理当前一共有5种实现方式(作者当前的版本是8.2.1),均在【 \Source\portable\MemMang 】下面,这里笔记下。
heap_1.c:
/* * The simplest possible implementation of pvPortMalloc(). Note that this * implementation does NOT allow allocated memory to be freed again. * * See heap_2.c, heap_3.c and heap_4.c for alternative implementations, and the * memory management pages of http://www.FreeRTOS.org for more information. */ /* 一种非常简单的内存实现方式,内部实现就是一个大号的数组,而且申请的内存无法释放~~ */ #include <stdlib.h> /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining all the API functions to use the MPU wrappers. That should only be done when task.h is included from an application file. */ #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE #include "FreeRTOS.h" #include "task.h" #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE //由于可能会出现内存对齐问题,数组起始地址可能会前移,因此实际的数组大小可能小于申请的大小,这里为了简单,直接向前移动了portBYTE_ALIGNMENT个字节。 /* A few bytes might be lost to byte aligning the heap start address. */ #define configADJUSTED_HEAP_SIZE ( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT ) /* Allocate the memory for the heap. */ //采用静态数组的方式从栈上获取一块内存,用这块内存来模拟堆 //ucHeap就是申请的静态数组,configTOTAL_HEAP_SIZE就是数组大小 //xNextFreeByte表示已经使用的内存数量。 static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ]; static size_t xNextFreeByte = ( size_t ) 0; /*-----------------------------------------------------------*/ /* 申请内存,其实就是从ucHeap中获取一块内存,然后返回 */ void *pvPortMalloc( size_t xWantedSize ) { void *pvReturn = NULL; static uint8_t *pucAlignedHeap = NULL;//代码内部不直接使用ucHeap,而是使用该静态指针指向ucHeap,也就是可用内存的初始地址 /* 如果宏定义为内存对齐字节!=1,即申请内存不是1字节对齐,那么就把要申请的内存数量(xWantedSize)按照要求对齐 */ /* Ensure that blocks are always aligned to the required number of bytes. */ #if portBYTE_ALIGNMENT != 1 if( xWantedSize & portBYTE_ALIGNMENT_MASK ) { /* Byte alignment required. */ xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } #endif vTaskSuspendAll();//首先暂停当前所有执行的任务 { //初始化静态指针 if( pucAlignedHeap == NULL ) { //保证pucAlignedHeap也是在按照指定内存要求对齐的,通过这里可以知道,初始化pucAlignedHeap时并不是一定等于&ucHeap[0]的,而是会根据字节对齐的要求,在 //&ucHeap[0]和&ucHeap[portBYTE_ALIGNMENT]之间,这就会导致ucHeap的前几个字节可能会被浪费到,这也是为什么会有一个configADJUSTED_HEAP_SIZE。 /* Ensure the heap starts on a correctly aligned boundary. */ pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) ); } //如果已经使用的内存数量 + 新申请的 < 能够提供的,那么就从数组中取一块。 /* Check there is enough room left for the allocation. */ if( ( ( 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();//恢复执行 //如果定义了钩子函数,那么申请失败时就调用钩子函数 #if( configUSE_MALLOC_FAILED_HOOK == 1 ) { if( pvReturn == NULL ) { extern void vApplicationMallocFailedHook( void ); vApplicationMallocFailedHook(); } } #endif return pvReturn; } /*-----------------------------------------------------------*/ /* vPortFree 什么也不做,xNextFreeByte只会增加,不会减小,因此数组中的内存一旦使用,就再也不会被回收 */ 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 http://www.FreeRTOS.org for more information. */ ( void ) pv; /* Force an assert as it is invalid to call this function. */ configASSERT( pv == NULL ); } /*-----------------------------------------------------------*/ /* 初始化,由于所有的内存都是静态的,因此只要对xNextFreeByte进行赋值即可 */ void vPortInitialiseBlocks( void ) { /* Only required when static memory is not cleared. */ xNextFreeByte = ( size_t ) 0; } /*-----------------------------------------------------------*/ /*获取当前可用内存 */ size_t xPortGetFreeHeapSize( void ) { return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); }
发表评论