freertos 內存分配 源碼分析

xBlockLinkspa

typedef struct A_BLOCK_LINK
{
	struct A_BLOCK_LINK *pxNextFreeBlock;	/*<< The next free block in the list. */
	size_t xBlockSize;	/*<< The size of the free block. */
} xBlockLink;

堆棧初始化code

static xBlockLink xStart, xEnd;內存

static union xRTOS_HEAPit

{io

#if portBYTE_ALIGNMENT == 8    //這裏爲 8event

volatile portDOUBLE dDummy;ast

#elseclass

volatile unsigned long ulDummy;原理

#endifsed

unsigned char ucHeap[ configTOTAL_HEAP_SIZE ];

} xHeap;

#define prvHeapInit()																\
{																					\
xBlockLink *pxFirstFreeBlock;														\
	/* xStart is used to hold a pointer to the first item in the list of free */	\
	/* blocks.  The void cast is used to prevent compiler warnings. */				\
	xStart.pxNextFreeBlock = ( void * ) xHeap.ucHeap;								\
	xStart.xBlockSize = ( size_t ) 0;												\													\
	/* xEnd is used to mark the end of the list of free blocks. */					\
	xEnd.xBlockSize = configTOTAL_HEAP_SIZE;	//17*1024 17字節									\
	xEnd.pxNextFreeBlock = NULL;													\
	/* To start with there is a single free block that is sized to take up the		\
	entire heap space. */															\
	pxFirstFreeBlock = ( void * ) xHeap.ucHeap;										\
	pxFirstFreeBlock->xBlockSize = configTOTAL_HEAP_SIZE;							\
	pxFirstFreeBlock->pxNextFreeBlock = &xEnd;										\
}

內存

static const unsigned short  heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );

void *pvPortMalloc( size_t xWantedSize )
{
xBlockLink *pxBlock, *pxPreviousBlock, *pxNewBlockLink;
static portBASE_TYPE xHeapHasBeenInitialised = pdFALSE;
void *pvReturn = NULL;

	vTaskSuspendAll();
	{
	        //第一次
		if( xHeapHasBeenInitialised == pdFALSE )
		{
			prvHeapInit();
			xHeapHasBeenInitialised = pdTRUE;
		}

		if( xWantedSize > 0 )
		{
			xWantedSize += heapSTRUCT_SIZE;

			if( xWantedSize & portBYTE_ALIGNMENT_MASK ) //須要的空間對齊
			{
				xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
			}
		}

		if( ( xWantedSize > 0 ) && ( xWantedSize < configTOTAL_HEAP_SIZE ) )
		{
			pxPreviousBlock = &xStart;  //指向起始地址
			pxBlock = xStart.pxNextFreeBlock;  //
			while( ( pxBlock->xBlockSize < xWantedSize ) && ( pxBlock->pxNextFreeBlock ) )
			{
				pxPreviousBlock = pxBlock;   //找到合適大小
				pxBlock = pxBlock->pxNextFreeBlock;  //
			}

			if( pxBlock != &xEnd )
			{
				pvReturn = ( void * ) ( ( ( unsigned char * ) pxPreviousBlock->pxNextFreeBlock ) + heapSTRUCT_SIZE );  //得到分配的須要的空間地址

				/* 從空閒的內存鏈表中移除 */
				pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock;

				/*若是比須要的大,能夠分爲兩塊*/
				if( ( pxBlock->xBlockSize - xWantedSize ) > heapMINIMUM_BLOCK_SIZE )
				{
					pxNewBlockLink = ( void * ) ( ( ( unsigned char * ) pxBlock ) + xWantedSize ); 
					pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize;
					//新劃分出來的空間塊
					pxBlock->xBlockSize = xWantedSize;

					/* 把新分配的空間塊 添加到 空閒塊鏈表中 */
					prvInsertBlockIntoFreeList( ( pxNewBlockLink ) );
				}
				
				xFreeBytesRemaining -= pxBlock->xBlockSize; //空閒塊大小減去剛剛用掉的大小
			}
		}
	}
	xTaskResumeAll();

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

	return pvReturn;  //返回需求的內存空間地址
}

static const unsigned short  heapSTRUCT_SIZE = ( sizeof( xBlockLink ) + portBYTE_ALIGNMENT - ( sizeof( xBlockLink ) % portBYTE_ALIGNMENT ) );  //分配的塊空間對齊

分配內存對齊原理:如size大小15 原理就爲 15+8-(15%8)=16 爲2個8字節 

相關文章
相關標籤/搜索