好记性不如铅笔头

ARM, FreeRTOS, 操作系统

FreeRTOS代码阅读笔记:heap_1.c

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 );
}

 

发表评论

10 + 12 =

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据