本文共 6772 字,大约阅读时间需要 22 分钟。
所谓dynamic_mem就是指可以随时指定一段内存,让程序可以从这段内存中申请内存。dynamic_mem的例程如下:UINT32 Example_Dyn_Mem(VOID){ UINT32 *p_num = NULL; UINT32 uwRet;#初始化一段动态内存,形参pDynMem是段内存的起始地址,MEM_DYN_SIZE是这段内存的大小 uwRet = LOS_MemInit(pDynMem, MEM_DYN_SIZE); if (LOS_OK == uwRet) { dprintf("mempool init ok!\n"); } else { dprintf("mempool init failed!\n"); return LOS_NOK; } /* mem alloc */#从前面初始化好的内存中申请内存卡 p_num = (UINT32 *)LOS_MemAlloc(pDynMem, 4); if (NULL == p_num) { dprintf("mem alloc failed!\n"); return LOS_NOK; } dprintf("mem alloc ok\n"); /* assignment */ *p_num = 828; dprintf("*p_num = %d\n", *p_num); /* mem free */#将申请的内存块返回给pDynMem uwRet = LOS_MemFree(pDynMem, p_num); if (LOS_OK == uwRet) { dprintf("mem free ok!\n"); uwRet = LOS_InspectStatusSetByID(LOS_INSPECT_DMEM, LOS_INSPECT_STU_SUCCESS); if (LOS_OK != uwRet) { dprintf("Set Inspect Status Err\n"); } } else { dprintf("mem free failed!\n"); uwRet = LOS_InspectStatusSetByID(LOS_INSPECT_DMEM, LOS_INSPECT_STU_ERROR); if (LOS_OK != uwRet) { dprintf("Set Inspect Status Err\n"); } return LOS_NOK; } return LOS_OK;}用法清楚后,我们先看看如何初始化这段内存LITE_OS_SEC_TEXT_INIT UINT32 LOS_MemInit(VOID *pPool, UINT32 uwSize){ BOOL bRet = TRUE; UINTPTR uvIntSave;#可以支持多了不连续的内存,这样提供mempool的指针连在g_pPoolHead中#if (LOSCFG_MEM_MUL_POOL == YES) VOID *pNext = g_pPoolHead; VOID * pCur = g_pPoolHead; UINT32 uwPoolEnd;#endif if (!pPool || uwSize <= sizeof(struct LOS_HEAP_MANAGER)) return LOS_NOK; if (!IS_ALIGNED(pPool, OS_MEM_POOL_BASE_ALIGN)) return LOS_NOK; uvIntSave = LOS_IntLock();#multi pool中查找符合此次分配的mempool#if (LOSCFG_MEM_MUL_POOL == YES) while (pNext != NULL) { uwPoolEnd = (UINT32)pNext + ((struct LOS_HEAP_MANAGER *)pNext)->uwSize; if ((pPool <= pNext && ((UINT32)pPool + uwSize) > (UINT32)pNext) || ((UINT32)pPool < uwPoolEnd && ((UINT32)pPool + uwSize) >= uwPoolEnd)) { PRINT_ERR("pool [%p, 0x%x) conflict with pool [%p, 0x%x)\n", pPool, (UINT32)pPool + uwSize, pNext, (UINT32)pNext + ((struct LOS_HEAP_MANAGER *)pNext)->uwSize); LOS_IntRestore(uvIntSave); return LOS_NOK; } pCur = pNext; pNext = ((struct LOS_HEAP_MANAGER *)pNext)->pNextPool; }#endif#核心的初始化 bRet = osHeapInit(pPool, uwSize); if(!bRet) { LOS_IntRestore(uvIntSave); return LOS_NOK; }#还可以使用slab 减少内存碎片#if (LOSCFG_KERNEL_MEM_SLAB == YES) if (uwSize >= SLAB_BASIC_NEED_SIZE)//if size of pool is small than size of slab need, don`t init slab { bRet = osSlabMemInit(pPool); if(!bRet) { LOS_IntRestore(uvIntSave); return LOS_NOK; } }#endif LOS_IntRestore(uvIntSave); return LOS_OK;}继续看LITE_OS_SEC_TEXT_INIT BOOL osHeapInit(VOID *pPool, UINT32 uwSz){ struct LOS_HEAP_NODE* pstNode; struct LOS_HEAP_MANAGER *pstHeapMan = HEAP_CAST(struct LOS_HEAP_MANAGER *, pPool); if (!pstHeapMan || (uwSz <= (sizeof(struct LOS_HEAP_NODE) + sizeof(struct LOS_HEAP_MANAGER)))) return FALSE;#对mempool中的内容清零 memset(pPool, 0, uwSz); pstHeapMan->uwSize = uwSz;#将整个mempool 作为一个节点 pstNode = pstHeapMan->pstHead = (struct LOS_HEAP_NODE*)((UINT8*)pPool + sizeof(struct LOS_HEAP_MANAGER));#尾节点也指向这个节点 pstHeapMan->pstTail = pstNode; pstNode->uwUsed = 0; pstNode->pstPrev = NULL;#这个mempool可以提供分配到size pstNode->uwSize = uwSz - sizeof(struct LOS_HEAP_NODE) - sizeof(struct LOS_HEAP_MANAGER); return TRUE;}下来我们看看分配函数的实现LITE_OS_SEC_TEXT VOID* osHeapAlloc(VOID *pPool, UINT32 uwSz){ struct LOS_HEAP_NODE *pstNode, *pstT, *pstBest = NULL; VOID* pRet = NULL; UINT32 uvIntSave;#得到提供内存pool的头指针 struct LOS_HEAP_MANAGER *pstHeapMan = HEAP_CAST(struct LOS_HEAP_MANAGER *, pPool); if (!pstHeapMan) { return NULL; } uvIntSave = LOS_IntLock(); uwSz = ALIGNE(uwSz);#得到提供内存pool的尾指针 pstNode = pstHeapMan->pstTail; while (pstNode) {#找到一个size 大于等于要分配uwSz的内存段 if (!pstNode->uwUsed && pstNode->uwSize >= uwSz && (!pstBest || pstBest->uwSize > pstNode->uwSize)) {#找到要从中分配的内存段 pstBest = pstNode;#这个段的size刚好等于要分配的size if (pstBest->uwSize == uwSz) { goto SIZE_MATCH; } } pstNode = pstNode->pstPrev; } if (!pstBest) /*alloc failed*/ { PRINT_ERR("there's not enough whole to alloc %x Bytes!\n",uwSz); goto out; }#如果要分配的pool 大于需要的size,则将这个pool分成两部分,一部分分给用户,一部分加到链表中以备下一次使用 if (pstBest->uwSize - uwSz > sizeof(struct LOS_HEAP_NODE)) { /* hole divide into 2 */ pstNode = (struct LOS_HEAP_NODE*)(pstBest->ucData + uwSz); pstNode->uwUsed = 0; pstNode->uwSize = pstBest->uwSize - uwSz- sizeof(struct LOS_HEAP_NODE); pstNode->pstPrev = pstBest;#将剩下的size作为一个节点加到链表中 if (pstBest != pstHeapMan->pstTail) { if ((pstT = osHeapPrvGetNext(pstHeapMan, pstNode)) != NULL) pstT->pstPrev = pstNode; } else pstHeapMan->pstTail = pstNode; pstBest->uwSize = uwSz; }SIZE_MATCH: pstBest->uwAlignFlag = 0; pstBest->uwUsed = 1; pRet = pstBest->ucData;#是要使能task的统计信息#if (LOSCFG_MEM_TASK_USED_STATISTICS == YES) OS_MEM_ADD_USED(pstBest->uwSize);#endif return pRet;}最后看看内存的释放函数LITE_OS_SEC_TEXT BOOL osHeapFree(VOID *pPool, VOID* pPtr){ struct LOS_HEAP_NODE *pstNode, *pstT; UINT32 uvIntSave; BOOL bRet = TRUE; struct LOS_HEAP_MANAGER *pstHeapMan = HEAP_CAST(struct LOS_HEAP_MANAGER *, pPool); if (!pstHeapMan || !pPtr) { return LOS_NOK; } /* set to unused status */ pstNode->uwUsed = 0;#if (LOSCFG_MEM_TASK_USED_STATISTICS == YES) OS_MEM_REDUCE_USED(pstNode->uwSize);#endif#if (LOSCFG_HEAP_MEMORY_PEAK_STATISTICS == YES) if (g_uwCurHeapUsed >= (pstNode->uwSize + sizeof(struct LOS_HEAP_NODE))) { g_uwCurHeapUsed -= (pstNode->uwSize + sizeof(struct LOS_HEAP_NODE)); }#endif#按size大小找到这段内存要释放到list中的位置 /* unused region before and after combination */ while (pstNode->pstPrev && !pstNode->pstPrev->uwUsed) pstNode = pstNode->pstPrev;#将两块相邻的内存合并,类似于伙伴系统 while (((pstT = osHeapPrvGetNext(pstHeapMan, pstNode)) != NULL) && !pstT->uwUsed) { pstNode->uwSize += sizeof(struct LOS_HEAP_NODE) + pstT->uwSize; if (pstHeapMan->pstTail == pstT) pstHeapMan->pstTail = pstNode; } if ((pstT = osHeapPrvGetNext(pstHeapMan, pstNode)) != NULL) pstT->pstPrev = pstNode;OUT: LOS_IntRestore(uvIntSave); if (TRUE == bRet) { g_uwFreeCount++; } return bRet;}
转载地址:http://epnmi.baihongyu.com/