# å †å†…å˜ç®¡ç† ## 基本概念 内å˜ç®¡ç†æ¨¡å—管ç†ç³»ç»Ÿçš„内å˜èµ„æºï¼Œå®ƒæ˜¯æ“ä½œç³»ç»Ÿçš„æ ¸å¿ƒæ¨¡å—之一,主è¦åŒ…括内å˜çš„åˆå§‹åŒ–ã€åˆ†é…以åŠé‡Šæ”¾ã€‚OpenHarmony LiteOS-Açš„å †å†…å˜ç®¡ç†æä¾›å†…å˜åˆå§‹åŒ–ã€åˆ†é…ã€é‡Šæ”¾ç‰åŠŸèƒ½ã€‚åœ¨ç³»ç»Ÿè¿è¡Œè¿‡ç¨‹ä¸ï¼Œå †å†…å˜ç®¡ç†æ¨¡å—通过对内å˜çš„申请/释放æ¥ç®¡ç†ç”¨æˆ·å’ŒOS对内å˜çš„使用,使内å˜çš„åˆ©ç”¨çŽ‡å’Œä½¿ç”¨æ•ˆçŽ‡è¾¾åˆ°æœ€ä¼˜ï¼ŒåŒæ—¶æœ€å¤§é™åº¦åœ°è§£å†³ç³»ç»Ÿçš„内å˜ç¢Žç‰‡é—®é¢˜ã€‚ ## è¿è¡Œæœºåˆ¶ å †å†…å˜ç®¡ç†ï¼Œå³åœ¨å†…å˜èµ„æºå……è¶³çš„æƒ…å†µä¸‹ï¼Œæ ¹æ®ç”¨æˆ·éœ€æ±‚,从系统é…ç½®çš„ä¸€å—æ¯”较大的连ç»å†…å˜ï¼ˆå†…å˜æ± ï¼Œä¹Ÿæ˜¯å †å†…å˜ï¼‰ä¸åˆ†é…ä»»æ„大å°çš„内å˜å—。当用户ä¸éœ€è¦è¯¥å†…å˜å—时,åˆå¯ä»¥é‡Šæ”¾å›žç³»ç»Ÿä¾›ä¸‹ä¸€æ¬¡ä½¿ç”¨ã€‚ä¸Žé™æ€å†…å˜ç›¸æ¯”,动æ€å†…å˜ç®¡ç†çš„优点是按需分é…ï¼Œç¼ºç‚¹æ˜¯å†…å˜æ± ä¸å®¹æ˜“出现碎片。OpenHarmony LiteOS-Aå †å†…å˜åœ¨TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,é™ä½Žäº†ç¢Žç‰‡çŽ‡ã€‚åŠ¨æ€å†…å˜æ ¸å¿ƒç®—法框图如下: **图1** å°åž‹ç³»ç»ŸåЍæ€å†…å˜æ ¸å¿ƒç®—法  æ ¹æ®ç©ºé—²å†…å˜å—的大å°ï¼Œä½¿ç”¨å¤šä¸ªç©ºé—²é“¾è¡¨æ¥ç®¡ç†ã€‚æ ¹æ®å†…å˜ç©ºé—²å—大å°åˆ†ä¸ºä¸¤ä¸ªéƒ¨åˆ†ï¼š[4, 127]å’Œ[2<sup>7</sup>, 2<sup>31</sup>],如上图size class所示: 1. 对[4,127]区间的内å˜è¿›è¡Œç‰åˆ†ï¼Œå¦‚上图下åŠéƒ¨åˆ†æ‰€ç¤ºï¼Œåˆ†ä¸º31个å°åŒºé—´ï¼Œæ¯ä¸ªå°åŒºé—´å¯¹åº”内å˜å—大å°ä¸º4å—èŠ‚çš„å€æ•°ã€‚æ¯ä¸ªå°åŒºé—´å¯¹åº”一个空闲内å˜é“¾è¡¨å’Œç”¨äºŽæ ‡è®°å¯¹åº”空闲内å˜é“¾è¡¨æ˜¯å¦ä¸ºç©ºçš„一个比特ä½ï¼Œå€¼ä¸º1时,空闲链表éžç©ºã€‚[4,127]区间的31个å°åŒºé—´å†…å˜å¯¹åº”31个比特ä½è¿›è¡Œæ ‡è®°é“¾è¡¨æ˜¯å¦ä¸ºç©ºã€‚ 2. 大于127å—节的空闲内å˜å—,按照2的次幂区间大å°è¿›è¡Œç©ºé—²é“¾è¡¨ç®¡ç†ã€‚总共分为24个å°åŒºé—´ï¼Œæ¯ä¸ªå°åŒºé—´åˆç‰åˆ†ä¸º8个二级å°åŒºé—´ï¼Œè§ä¸Šå›¾ä¸ŠåŠéƒ¨åˆ†çš„Size Classå’ŒSize SubClass部分。æ¯ä¸ªäºŒçº§å°åŒºé—´å¯¹åº”ä¸€ä¸ªç©ºé—²é“¾è¡¨å’Œç”¨äºŽæ ‡è®°å¯¹åº”ç©ºé—²å†…å˜é“¾è¡¨æ˜¯å¦ä¸ºç©ºçš„一个比特ä½ã€‚总共24\*8=192个二级å°åŒºé—´ï¼Œå¯¹åº”192个空闲链表和192个比特ä½è¿›è¡Œæ ‡è®°é“¾è¡¨æ˜¯å¦ä¸ºç©ºã€‚ 例如,当有40å—节的空闲内å˜éœ€è¦æ’入空闲链表时,对应å°åŒºé—´[40,43],第10个空闲链表,ä½å›¾æ ‡è®°çš„第10比特ä½ã€‚把40å—èŠ‚çš„ç©ºé—²å†…å˜æŒ‚载第10ä¸ªç©ºé—²é“¾è¡¨ä¸Šï¼Œå¹¶åˆ¤æ–æ˜¯å¦éœ€è¦æ›´æ–°ä½å›¾æ ‡è®°ã€‚当需è¦ç”³è¯·40å—èŠ‚çš„å†…å˜æ—¶ï¼Œæ ¹æ®ä½å›¾æ ‡è®°èŽ·å–å˜åœ¨æ»¡è¶³ç”³è¯·å¤§å°çš„内å˜å—的空闲链表,从空闲链表上获å–空闲内å˜èŠ‚ç‚¹ã€‚å¦‚æžœåˆ†é…的节点大于需è¦ç”³è¯·çš„内å˜å¤§å°ï¼Œè¿›è¡Œåˆ†å‰²èŠ‚ç‚¹æ“ä½œï¼Œå‰©ä½™çš„èŠ‚ç‚¹é‡æ–°æŒ‚载到相应的空闲链表上。当有580å—节的空闲内å˜éœ€è¦æ’入空闲链表时,对应二级å°åŒºé—´[2^9,2^9+2^6],第31+2\*8=47个空闲链表,并使用ä½å›¾çš„第47ä¸ªæ¯”ç‰¹ä½æ¥æ ‡è®°é“¾è¡¨æ˜¯å¦ä¸ºç©ºã€‚把580å—èŠ‚çš„ç©ºé—²å†…å˜æŒ‚载第47ä¸ªç©ºé—²é“¾è¡¨ä¸Šï¼Œå¹¶åˆ¤æ–æ˜¯å¦éœ€è¦æ›´æ–°ä½å›¾æ ‡è®°ã€‚当需è¦ç”³è¯·580å—èŠ‚çš„å†…å˜æ—¶ï¼Œæ ¹æ®ä½å›¾æ ‡è®°èŽ·å–å˜åœ¨æ»¡è¶³ç”³è¯·å¤§å°çš„内å˜å—的空闲链表,从空闲链表上获å–空闲内å˜èŠ‚ç‚¹ã€‚å¦‚æžœåˆ†é…的节点大于需è¦ç”³è¯·çš„内å˜å¤§å°ï¼Œè¿›è¡Œåˆ†å‰²èŠ‚ç‚¹æ“ä½œï¼Œå‰©ä½™çš„èŠ‚ç‚¹é‡æ–°æŒ‚è½½åˆ°ç›¸åº”çš„ç©ºé—²é“¾è¡¨ä¸Šã€‚å¦‚æžœå¯¹åº”çš„ç©ºé—²é“¾è¡¨ä¸ºç©ºï¼Œåˆ™å‘æ›´å¤§çš„内å˜åŒºé—´åŽ»æŸ¥è¯¢æ˜¯å¦æœ‰æ»¡è¶³æ¡ä»¶çš„空闲链表,实际计算时,会一次性查找到满足申请大å°çš„空闲链表。 内å˜ç®¡ç†ç»“构如下图所示: **图2** å°åž‹ç³»ç»ŸåЍæ€å†…å˜ç®¡ç†ç»“构图  - å†…å˜æ± æ± å¤´éƒ¨åˆ† å†…å˜æ± æ± å¤´éƒ¨åˆ†åŒ…å«å†…å˜æ± ä¿¡æ¯ã€ä½å›¾æ ‡è®°æ•°ç»„å’Œç©ºé—²é“¾è¡¨æ•°ç»„ã€‚å†…å˜æ± ä¿¡æ¯åŒ…å«å†…å˜æ± 起始地å€åŠå †åŒºåŸŸæ€»å¤§å°ï¼Œå†…å˜æ± 属性。ä½å›¾æ ‡è®°æ•°ç»„有7个32使— ç¬¦å·æ•´æ•°ç»„æˆï¼Œæ¯ä¸ªæ¯”ç‰¹ä½æ ‡è®°å¯¹åº”çš„ç©ºé—²é“¾è¡¨æ˜¯å¦æŒ‚载空闲内å˜å—节点。空闲内å˜é“¾è¡¨åŒ…å«223个空闲内å˜å¤´èŠ‚ç‚¹ä¿¡æ¯ï¼Œæ¯ä¸ªç©ºé—²å†…å˜å¤´èŠ‚ç‚¹ä¿¡æ¯ç»´æŠ¤å†…å˜èŠ‚ç‚¹å¤´å’Œç©ºé—²é“¾è¡¨ä¸çš„å‰é©±ã€åŽç»§ç©ºé—²å†…å˜èŠ‚ç‚¹ã€‚ - å†…å˜æ± 节点部分 包å«3ç§ç±»åž‹èŠ‚ç‚¹ï¼šæœªä½¿ç”¨ç©ºé—²å†…å˜èŠ‚ç‚¹ï¼Œå·²ä½¿ç”¨å†…å˜èŠ‚ç‚¹å’Œå°¾èŠ‚ç‚¹ã€‚æ¯ä¸ªå†…å˜èŠ‚ç‚¹ç»´æŠ¤ä¸€ä¸ªå‰åºæŒ‡é’ˆï¼ŒæŒ‡å‘å†…å˜æ± ä¸ä¸Šä¸€ä¸ªå†…å˜èŠ‚ç‚¹ï¼Œè¿˜ç»´æŠ¤å†…å˜èŠ‚ç‚¹çš„å¤§å°å’Œä½¿ç”¨æ ‡è®°ã€‚空闲内å˜èŠ‚ç‚¹å’Œå·²ä½¿ç”¨å†…å˜èŠ‚ç‚¹åŽé¢çš„内å˜åŒºåŸŸæ˜¯æ•°æ®åŸŸï¼Œå°¾èŠ‚ç‚¹æ²¡æœ‰æ•°æ®åŸŸã€‚ ## 开呿Œ‡å¯¼ ### 使用场景 å †å†…å˜ç®¡ç†çš„主è¦å·¥ä½œæ˜¯åЍæ€åˆ†é…并管ç†ç”¨æˆ·ç”³è¯·åˆ°çš„内å˜åŒºé—´ï¼Œä¸»è¦ç”¨äºŽç”¨æˆ·éœ€è¦ä½¿ç”¨å¤§å°ä¸ç‰çš„内å˜å—的场景,当用户需è¦ä½¿ç”¨å†…å˜æ—¶ï¼Œå¯ä»¥é€šè¿‡æ“作系统的动æ€å†…å˜ç”³è¯·å‡½æ•°ç´¢å–指定大å°çš„内å˜å—。一旦使用完毕,通过内å˜é‡Šæ”¾å‡½æ•°é‡Šæ”¾æ‰€å 用内å˜ï¼Œä½¿ä¹‹å¯ä»¥é‡å¤ä½¿ç”¨ã€‚ ### 接å£è¯´æ˜Ž OpenHarmony LiteOS-Açš„å †å†…å˜ç®¡ç†ä¸»è¦ä¸ºç”¨æˆ·æä¾›ä»¥ä¸‹åŠŸèƒ½ï¼ŒæŽ¥å£è¯¦ç»†ä¿¡æ¯å¯ä»¥æŸ¥çœ‹APIå‚考。 **表1** å †å†…å˜ç®¡ç†æŽ¥å£ | 功能分类 | æŽ¥å£æè¿° | | -------- | -------- | | åˆå§‹åŒ–å’Œåˆ é™¤å†…å˜æ± | - LOS_MemInit:åˆå§‹åŒ–䏀嗿Œ‡å®šçš„动æ€å†…å˜æ± ,大å°ä¸ºsize<br/>- LOS_MemDeInitï¼šåˆ é™¤æŒ‡å®šå†…å˜æ± ,仅打开LOSCFG_MEM_MUL_POOL时有效 | | 申请ã€é‡Šæ”¾åЍæ€å†…å˜ | - LOS_MemAlloc:从指定动æ€å†…å˜æ± ä¸ç”³è¯·size长度的内å˜<br/>- LOS_MemFree:释放从指定动æ€å†…å˜ä¸ç”³è¯·çš„内å˜<br/>- LOS_MemRealloc:<br/>- 按size大å°é‡æ–°åˆ†é…内å˜å—,并将原内å˜å—内容拷è´åˆ°æ–°å†…å˜å—。如果新内å˜å—申请æˆåŠŸï¼Œåˆ™é‡Šæ”¾åŽŸå†…å˜å—<br/>- LOS_MemAllocAlign:从指定动æ€å†…å˜æ± ä¸ç”³è¯·é•¿åº¦ä¸ºsizeä¸”åœ°å€æŒ‰boundaryå—节对é½çš„å†…å˜ | | 获å–å†…å˜æ± ä¿¡æ¯ | - LOS_MemPoolSizeGetï¼šèŽ·å–æŒ‡å®šåЍæ€å†…å˜æ± 的总大å°<br/>- LOS_MemTotalUsedGetï¼šèŽ·å–æŒ‡å®šåЍæ€å†…å˜æ± 的总使用é‡å¤§å°<br/>- LOS_MemInfoGetï¼šèŽ·å–æŒ‡å®šå†…å˜æ± 的内å˜ç»“构信æ¯ï¼ŒåŒ…括空闲内å˜å¤§å°ã€å·²ä½¿ç”¨å†…å˜å¤§å°ã€ç©ºé—²å†…å˜å—æ•°é‡ã€å·²ä½¿ç”¨çš„内å˜å—æ•°é‡ã€æœ€å¤§çš„空闲内å˜å—大å°<br/>- LOS_MemPoolList:打å°ç³»ç»Ÿä¸å·²åˆå§‹åŒ–çš„æ‰€æœ‰å†…å˜æ± ï¼ŒåŒ…æ‹¬å†…å˜æ± 的起始地å€ã€å†…å˜æ± 大å°ã€ç©ºé—²å†…å˜æ€»å¤§å°ã€å·²ä½¿ç”¨å†…å˜æ€»å¤§å°ã€æœ€å¤§çš„空闲内å˜å—大å°ã€ç©ºé—²å†…å˜å—æ•°é‡ã€å·²ä½¿ç”¨çš„内å˜å—æ•°é‡ã€‚仅打开LOSCFG_MEM_MUL_POOL时有效 | | 获å–内å˜å—ä¿¡æ¯ | LOS_MemFreeNodeShowï¼šæ‰“å°æŒ‡å®šå†…å˜æ± 的空闲内å˜å—的大å°åŠæ•°é‡ | | æ£€æŸ¥æŒ‡å®šå†…å˜æ± 的完整性 | LOS_MemIntegrityCheckï¼šå¯¹æŒ‡å®šå†…å˜æ± åšå®Œæ•´æ€§æ£€æŸ¥ï¼Œä»…打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效 | >  **说明:** > - 由于动æ€å†…å˜ç®¡ç†éœ€è¦ç®¡ç†æŽ§åˆ¶å—æ•°æ®ç»“æž„æ¥ç®¡ç†å†…å˜ï¼Œè¿™äº›æ•°æ®ç»“构会é¢å¤–消耗内å˜ï¼Œæ•…实际用户å¯ä½¿ç”¨å†…å˜æ€»é‡å°äºŽé…置项OS_SYS_MEM_SIZE的大å°ã€‚ > > - 对é½åˆ†é…å†…å˜æŽ¥å£LOS_MemAllocAlign/LOS_MemMallocAlignå› ä¸ºè¦è¿›è¡Œåœ°å€å¯¹é½ï¼Œå¯èƒ½ä¼šé¢å¤–消耗部分内å˜ï¼Œæ•…å˜åœ¨ä¸€äº›é—失内å˜ï¼Œå½“系统释放该对é½å†…å˜æ—¶ï¼ŒåŒæ—¶å›žæ”¶ç”±äºŽå¯¹é½å¯¼è‡´çš„é—失内å˜ã€‚ ### 开呿µç¨‹ 本节介ç»ä½¿ç”¨åЍæ€å†…å˜çš„å…¸åž‹åœºæ™¯å¼€å‘æµç¨‹ã€‚ 1. åˆå§‹åŒ–LOS_MemInit。 åˆå§‹ä¸€ä¸ªå†…å˜æ± åŽç”Ÿæˆä¸€ä¸ªå†…å˜æ± 控制头ã€å°¾èŠ‚ç‚¹EndNode,剩余的内å˜è¢«æ ‡è®°ä¸ºFreeNode内å˜èŠ‚ç‚¹ã€‚æ³¨ï¼šEndNodeä½œä¸ºå†…å˜æ± 末尾的节点,size为0。 1. 申请任æ„大å°çš„动æ€å†…å˜LOS_MemAlloc。 判æ–动æ€å†…å˜æ± 䏿˜¯å¦å˜åœ¨å¤§äºŽç”³è¯·é‡å¤§å°çš„空闲内å˜å—空间,若å˜åœ¨ï¼Œåˆ™åˆ’出一å—内å˜å—,以指针形å¼è¿”回,若ä¸å˜åœ¨ï¼Œè¿”回NULL。如果空闲内å˜å—大于申请é‡ï¼Œéœ€è¦å¯¹å†…å˜å—进行分割,剩余的部分作为空闲内å˜å—挂载到空闲内å˜é“¾è¡¨ä¸Šã€‚ 1. 释放动æ€å†…å˜LOS_MemFree。 回收内å˜å—,供下一次使用。调用LOS_MemFree释放内å˜å—,则会回收内å˜å—ï¼Œå¹¶ä¸”å°†å…¶æ ‡è®°ä¸ºFreeNode。在回收内å˜å—时,相邻的FreeNode会自动åˆå¹¶ã€‚ ### 编程实例 本实例执行以下æ¥éª¤ï¼š 1. åˆå§‹åŒ–一个动æ€å†…å˜æ± 。 2. 从动æ€å†…å˜æ± ä¸ç”³è¯·ä¸€ä¸ªå†…å˜å—。 3. 在内å˜å—ä¸å˜æ”¾ä¸€ä¸ªæ•°æ®ã€‚ 4. 打å°å‡ºå†…å˜å—ä¸çš„æ•°æ®ã€‚ 5. 释放该内å˜å—。 示例代ç 如下: ``` #include "los_memory.h" #define TEST_POOL_SIZE (2*1024*1024) __attribute__((aligned(4))) UINT8 g_testPool[TEST_POOL_SIZE]; VOID Example_DynMem(VOID) { UINT32 *mem = NULL; UINT32 ret; /*åˆå§‹åŒ–å†…å˜æ± */ ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE); if (LOS_OK == ret) { printf("Mem init success!\n"); } else { printf("Mem init failed!\n"); return; } /*分é…内å˜*/ mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4); if (NULL == mem) { printf("Mem alloc failed!\n"); return; } printf("Mem alloc success!\n"); /*赋值*/ *mem = 828; printf("*mem = %d\n", *mem); /*释放内å˜*/ ret = LOS_MemFree(g_testPool, mem); if (LOS_OK == ret) { printf("Mem free success!\n"); } else { printf("Mem free failed!\n"); } return; } UINT32 ExampleDynMemEntry(VOID) { UINT32 ret; TSK_INIT_PARAM_S initParam = {0}; initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_DynMem; initParam.usTaskPrio = 10; initParam.pcName = "Example_DynMem"; initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; initParam.uwResved = LOS_TASK_STATUS_DETACHED; /* 创建高优先级任务,由于é”任务调度,任务创建æˆåŠŸåŽä¸ä¼šé©¬ä¸Šæ‰§è¡Œ */ ret = LOS_TaskCreate(&g_taskHiID, &initParam); if (ret != LOS_OK) { LOS_TaskUnlock(); PRINTK("Example_DynMem create Failed! ret=%d\n", ret); return LOS_NOK; } PRINTK("Example_DynMem create Success!\n"); while(1){}; return LOS_OK; } ``` ### ç»“æžœéªŒè¯ è¾“å‡ºç»“æžœå¦‚ä¸‹ï¼š ``` Mem init success! Mem alloc success! *mem = 828 Mem free success! ```