博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
liteos的动态内存的管理
阅读量:4215 次
发布时间:2019-05-26

本文共 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/

你可能感兴趣的文章
pm 源码分析
查看>>
Sending the User to Another App
查看>>
kmsg_dump
查看>>
Getting a Result from an Activity
查看>>
Allowing Other Apps to Start Your Activity
查看>>
dev/mem
查看>>
pfn_valid 源码分析
查看>>
dev/kmem 和dev/mem的区别
查看>>
checkbox
查看>>
Sending Simple Data to Other Apps
查看>>
Receiving Simple Data from Other Apps
查看>>
中断API之__tasklet_schedule
查看>>
中断API之enable_irq
查看>>
中断API之disable_irq
查看>>
nova 中的guestfs
查看>>
nova中的localfs
查看>>
utils/rpm_build.sh
查看>>
查看模块参数
查看>>
udev重命名网口
查看>>
pgrep
查看>>