溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

FreeRTOS動態(tài)內(nèi)存分配管理示例分析

發(fā)布時間:2022-04-07 10:03:02 來源:億速云 閱讀:293 作者:iii 欄目:開發(fā)技術(shù)

本篇內(nèi)容主要講解“FreeRTOS動態(tài)內(nèi)存分配管理示例分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“FreeRTOS動態(tài)內(nèi)存分配管理示例分析”吧!

動態(tài)內(nèi)存管理

FreeRTOS提供5種動態(tài)內(nèi)存管理策略,分別為heap_1到heap_5,源碼在FreeRTOS/Source/portable/MemMang下,本質(zhì)是對一個或者多個大數(shù)組進(jìn)行操作來對系統(tǒng)提供內(nèi)存的申請、釋放(有的策略沒有)功能。下面先看看heap_1是怎么做的。

heap_1.c 內(nèi)存堆管理

大數(shù)組在哪里

/* Allocate the memory for the heap. */
#if( configAPPLICATION_ALLOCATED_HEAP == 1 )
//這種情況是可以把待管理的數(shù)組分配在外部SRAM、SDRAM中
	extern uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#else
//這種情況是把待管理的數(shù)組分配在內(nèi)部RAM,由編譯器決定地址
	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
#endif /* configAPPLICATION_ALLOCATED_HEAP */

可以看到這個局部靜態(tài)全局大數(shù)組名字是ucHeap,大小是configTOTAL_HEAP_SIZE,這個宏在FreeRTOSConfig.h中定義

實(shí)際可用數(shù)組字節(jié)數(shù)

//因?yàn)樾枰止?jié)對齊,所以實(shí)際能使用的內(nèi)存字節(jié)數(shù)要減去portBYTE_ALIGNMENT
/* A few bytes might be lost to byte aligning the heap start address. */
#define configADJUSTED_HEAP_SIZE	( configTOTAL_HEAP_SIZE - portBYTE_ALIGNMENT )

portBYTE_ALIGNMENT 在portmacro.h中定義

#define portBYTE_ALIGNMENT8

已分配字節(jié)數(shù)

//已經(jīng)分配了的字節(jié)數(shù),也就是下一個空閑內(nèi)存相對于首址(pucAlignedHeap)的偏移量
static size_t xNextFreeByte = ( size_t ) 0;

分配

void *pvPortMalloc( size_t xWantedSize )
{
void *pvReturn = NULL;//待返回給用戶分配地址
static uint8_t *pucAlignedHeap = NULL;//實(shí)際管理的數(shù)組首地址
	/* Ensure that blocks are always aligned to the required number of bytes. */
    //如果不是1字節(jié)對齊則先需要portBYTE_ALIGNMENT字節(jié)對齊
	#if( portBYTE_ALIGNMENT != 1 )
	{
		if( xWantedSize & portBYTE_ALIGNMENT_MASK )
		{			/* Byte alignment required. */
		//如果用戶申請字節(jié)數(shù)不是portBYTE_ALIGNMENT_MASK字節(jié)對齊的,先要調(diào)整到portBYTE_ALIGNMENT_MASK字節(jié)對齊
		//比如申請13字節(jié),要求portBYTE_ALIGNMENT = 8,
		//則xWantedSize = 13+(8-(13&7))=13+(8-5)=16,
		//最終申請16字節(jié)
			xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) );
		}
	}
	#endif
//掛起調(diào)度器,防止函數(shù)重入
	vTaskSuspendAll();
	{
		if( pucAlignedHeap == NULL )
		//說明是第一次調(diào)用此函數(shù)需要對對內(nèi)存堆初始化確保內(nèi)存堆首址也是8字節(jié)對齊
		{
			/* Ensure the heap starts on a correctly aligned boundary. */
		    //假設(shè)&ucHeap是0x20000C64,
		    //則&ucHeap[ portBYTE_ALIGNMENT ]是 0x20000C64+7=0x20000C6B
		    //pucAlignedHeap = 0x20000C6B & (~0x00000007) = 0x20000C68
		    //pucAlignedHeap才是實(shí)際操作的堆首址
			pucAlignedHeap = ( uint8_t * ) ( ( ( portPOINTER_SIZE_TYPE ) &ucHeap[ portBYTE_ALIGNMENT ] ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
		}
		/* Check there is enough room left for the allocation. */
		//已經(jīng)分配的字節(jié)數(shù)xNextFreeByte + 將要分配的字節(jié)數(shù)xWantedSize
		//要小于總共有的字節(jié)數(shù)configADJUSTED_HEAP_SIZE
		if( ( ( xNextFreeByte + xWantedSize ) < configADJUSTED_HEAP_SIZE ) &&
		//此條件是防止溢出,因?yàn)閮?nèi)存是地址是單調(diào)增長
			( ( xNextFreeByte + xWantedSize ) > xNextFreeByte )	)/* Check for overflow. */
		{
			/* Return the next free byte then increment the index past this
			block. */
			//返回地址給用戶
			pvReturn = pucAlignedHeap + xNextFreeByte;
			//更新已經(jīng)分配了的內(nèi)存字節(jié)數(shù)
			xNextFreeByte += xWantedSize;
		}
		traceMALLOC( pvReturn, xWantedSize );
	}
	( void ) xTaskResumeAll();
//解掛調(diào)度器
//如果使能的內(nèi)存申請失敗的鉤子函數(shù)當(dāng)申請失敗時會執(zhí)行申請失敗鉤子函數(shù)
	#if( configUSE_MALLOC_FAILED_HOOK == 1 )
	{
		if( pvReturn == NULL )
		{
			extern void vApplicationMallocFailedHook( void );
			vApplicationMallocFailedHook();
		}
	}
	#endif
	return pvReturn;
}

其中portBYTE_ALIGNMENT_MASK是根據(jù)portBYTE_ALIGNMENT定義,在portable.h中

#if portBYTE_ALIGNMENT == 8
	#define portBYTE_ALIGNMENT_MASK ( 0x0007 )
#endif

釋放

可以看到heap_1是沒有提供釋放,是無法釋放的

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

還??臻e字節(jié)數(shù)

size_t xPortGetFreeHeapSize( void )
{
	return ( configADJUSTED_HEAP_SIZE - xNextFreeByte );
}

適用范圍、特點(diǎn)

適用于只需分配,不需釋放場合,執(zhí)行時間確定,不會產(chǎn)生碎片,但是內(nèi)存利用率不高

到此,相信大家對“FreeRTOS動態(tài)內(nèi)存分配管理示例分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI