網(wǎng)站首頁 編程語言 正文
動(dòng)態(tài)內(nèi)存管理
FreeRTOS提供5種動(dòng)態(tài)內(nèi)存管理策略,分別為heap_1到heap_5,源碼在FreeRTOS/Source/portable/MemMang下,本質(zhì)是對(duì)一個(gè)或者多個(gè)大數(shù)組進(jìn)行操作來對(duì)系統(tǒng)提供內(nèi)存的申請(qǐng)、釋放(有的策略沒有)功能。下面先看看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 */
可以看到這個(gè)局部靜態(tài)全局大數(shù)組名字是ucHeap
,大小是configTOTAL_HEAP_SIZE,這個(gè)宏在FreeRTOSConfig.h
中定義
實(shí)際可用數(shù)組字節(jié)數(shù)
//因?yàn)樾枰止?jié)對(duì)齊,所以實(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ù),也就是下一個(gè)空閑內(nèi)存相對(duì)于首址(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é)對(duì)齊則先需要portBYTE_ALIGNMENT字節(jié)對(duì)齊 #if( portBYTE_ALIGNMENT != 1 ) { if( xWantedSize & portBYTE_ALIGNMENT_MASK ) { /* Byte alignment required. */ //如果用戶申請(qǐng)字節(jié)數(shù)不是portBYTE_ALIGNMENT_MASK字節(jié)對(duì)齊的,先要調(diào)整到portBYTE_ALIGNMENT_MASK字節(jié)對(duì)齊 //比如申請(qǐng)13字節(jié),要求portBYTE_ALIGNMENT = 8, //則xWantedSize = 13+(8-(13&7))=13+(8-5)=16, //最終申請(qǐng)16字節(jié) xWantedSize += ( portBYTE_ALIGNMENT - ( xWantedSize & portBYTE_ALIGNMENT_MASK ) ); } } #endif //掛起調(diào)度器,防止函數(shù)重入 vTaskSuspendAll(); { if( pucAlignedHeap == NULL ) //說明是第一次調(diào)用此函數(shù)需要對(duì)對(duì)內(nèi)存堆初始化確保內(nèi)存堆首址也是8字節(jié)對(duì)齊 { /* 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)增長(zhǎng) ( ( 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)存申請(qǐng)失敗的鉤子函數(shù)當(dāng)申請(qǐng)失敗時(shí)會(huì)執(zhí)行申請(qǐng)失敗鉤子函數(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 ); }
還剩空閑字節(jié)數(shù)
size_t xPortGetFreeHeapSize( void ) { return ( configADJUSTED_HEAP_SIZE - xNextFreeByte ); }
適用范圍、特點(diǎn)
適用于只需分配,不需釋放場(chǎng)合,執(zhí)行時(shí)間確定,不會(huì)產(chǎn)生碎片,但是內(nèi)存利用率不高
原文鏈接:https://blog.csdn.net/weixin_41572450/article/details/107746378
相關(guān)推薦
- 2023-01-18 Go語言讀取YAML?配置文件的兩種方式分享_Golang
- 2022-11-28 C語言中g(shù)etchar()函數(shù)的用法小結(jié)_C 語言
- 2023-02-27 Python?input()函數(shù)案例教程_python
- 2023-11-20 【ROS】用roslibpy庫(kù)在windows上用python 連接Ubuntu ROS
- 2022-10-07 Docker超詳細(xì)講解鏡像操作_docker
- 2022-04-01 PyPy?如何讓Python代碼運(yùn)行得和C一樣快_python
- 2022-07-10 TypeError: Cannot read property ‘forceUpdate‘ of u
- 2022-02-05 Tableau:如何處理Excel中一個(gè)sheet中有多張表的問題?
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支