liteos的动态内存的管理

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/tiantao2012/article/details/86685452
所谓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;
}

猜你喜欢

转载自blog.csdn.net/tiantao2012/article/details/86685452