浅析μC/GUI-v3.98之GUI_ALLOC_AllocZero()内存申请转句柄hWin函数
文章来源:http://gliethttp.cublog.cn
------------------------------------------------------------------------------------- 1.GUI_ALLOC_AllocZero() gui/core/GUI_ALLOC_AllocZero.c GUI_HMEM GUI_ALLOC_AllocZero(GUI_ALLOC_DATATYPE Size) { GUI_HMEM hMem; GUI_LOCK(); GUI_DEBUG_LOG2("\nGUI_ALLOC_Alloc... requesting %d, %d avail", Size, GUI_ALLOC_GetMaxSize()); hMem = GUI_ALLOC_AllocNoInit(Size); //申请size大小的内存空间,返回对该内存空间的目录索引 if (hMem) { GUI_MEMSET((U8*)GUI_ALLOC_h2p(hMem), 0, Size); //填充0
} GUI_UNLOCK(); return hMem; } ------------------------------------------------------------------------------------- 2.GUI_ALLOC_AllocNoInit()函数 gui/core/GUIAlloc.c GUI_HMEM GUI_ALLOC_AllocNoInit(GUI_ALLOC_DATATYPE Size) { GUI_HMEM hMem; if (Size == 0) { return (GUI_HMEM)0; } GUI_LOCK(); GUI_DEBUG_LOG2("\nGUI_ALLOC_AllocNoInit... requesting %d, %d avail", Size, GUI_ALLOC.NumFreeBytes); hMem = _Alloc(Size); //申请size大小的内存空间,返回对该内存空间的目录索引 GUI_DEBUG_LOG1("\nGUI_ALLOC_AllocNoInit : Handle", hMem); GUI_UNLOCK(); return hMem; } ------------------------------------------------------------------------------------- 3._Alloc()函数 gui/core/GUIAlloc.c static GUI_HMEM _Alloc(GUI_ALLOC_DATATYPE size) { GUI_HMEM hMemNew, hMemIns; _CheckInit(); //检测GUI_ALLOC内存监控变量单元是否初始化,若未初始化,初始化之 size = _Size2LegalSize(size); //处理器字节对齐,可以是2字节,4字节 /* Check if memory is available at all ...*/ if (size > _GetNumFreeBytes()) { //返回空闲字节数GUI_ALLOC.NumFreeBytes GUI_DEBUG_WARN1("GUI_ALLOC_Alloc: Insufficient memory configured (Trying to alloc % bytes)", size); return 0; } /* Locate free handle */ if ((hMemNew = _FindFreeHandle()) == 0) { //2007-07-09 gliethttp申请内存空间的目录索引 return 0; } /* Locate or Create hole of sufficient size */ hMemIns = _FindHole(size); //查找紧邻的两个已用单元之间是否有size大小夹缝空间
#if GUI_ALLOC_AUTDEFRAG if (hMemIns == -1) { if (_LockCnt == 0) { hMemIns = _CreateHole(size); //没有夹缝空间,创建全新的内存单元,同时整理内存碎片 } } #endif /* Occupy hole */ if (hMemIns==-1) { GUI_DEBUG_ERROROUT1("GUI_ALLOC_Alloc: Could not allocate %d bytes",size); return 0; } { GUI_ALLOC_DATATYPE Off = aBlock[hMemIns].Off + aBlock[hMemIns].Size;//空闲内存起始地址偏移量Off int Next = aBlock[hMemIns].Next; //如果hMemIns是夹缝空间,那么将新单元hMemNew插入到hMemIns和hMemIns.Next之间 aBlock[hMemNew].Size = size; aBlock[hMemNew].Off = Off; if ((aBlock[hMemNew].Next = Next) >0) { aBlock[Next].Prev = hMemNew; //如果hMemIns是夹缝空间,完善双向链表 } aBlock[hMemNew].Prev = hMemIns; aBlock[hMemIns].Next = hMemNew; } /* Keep track of number of blocks and av. memory */ GUI_ALLOC.NumUsedBlocks++; //内存维护变量单元的更新 GUI_ALLOC.NumFreeBlocks--; if (GUI_ALLOC.NumFreeBlocksMin > GUI_ALLOC.NumFreeBlocks) { GUI_ALLOC.NumFreeBlocksMin = GUI_ALLOC.NumFreeBlocks; } GUI_ALLOC.NumUsedBytes += size; GUI_ALLOC.NumFreeBytes -= size; if (GUI_ALLOC.NumFreeBytesMin > GUI_ALLOC.NumFreeBytes) { GUI_ALLOC.NumFreeBytesMin = GUI_ALLOC.NumFreeBytes; } return hMemNew; //返回申请到的内存空间的目录索引 } ------------------------------------------------------------------------------------- 4._FindFreeHandle()函数 gui/core/GUIAlloc.c static GUI_HMEM _FindFreeHandle(void) { int i; for (i = _FirstFreeHandle; i < GUI_MAXBLOCKS; i++) { if (aBlock[i].Size == 0) { _FirstFreeHandle = i; //申请内存空间的目录索引,aBlock[i].Size==0表示该目录空闲 return i; } } GUI_DEBUG_ERROROUT1("Insufficient memory handles configured (GUI_MAXBLOCKS == %d (See GUIConf.h))", GUI_MAXBLOCKS); return GUI_HMEM_NULL; } ------------------------------------------------------------------------------------- 4._FindHole()函数 gui/core/GUIAlloc.c static GUI_HMEM _FindHole(GUI_ALLOC_DATATYPE Size) { int i, iNext; for (i=0; (iNext = aBlock[i].Next) != 0; i = iNext) { GUI_ALLOC_DATATYPE NumFreeBytes = aBlock[iNext].Off- (aBlock[i].Off+aBlock[i].Size); if (NumFreeBytes>=Size) { //查找紧邻的两个已用单元之间是否有size大小空间 return i; } } /* Check last block */ if (GUI_ALLOC_SIZE - (aBlock[i].Off+aBlock[i].Size) >= Size) { return i; } return -1; //无 } ------------------------------------------------------------------------------------- 4._CreateHole()函数 gui/core/GUIAlloc.c static GUI_HMEM _CreateHole(GUI_ALLOC_DATATYPE Size) { int i, iNext; int r = -1; for (i=0; (iNext =aBlock[i].Next) !=0; i= iNext) { //创建全新的内存单元,同时整理内存碎片 GUI_ALLOC_DATATYPE NumFreeBytes = aBlock[iNext].Off- (aBlock[i].Off+aBlock[i].Size); if (NumFreeBytes < Size) { GUI_ALLOC_DATATYPE NumBytesBeforeBlock = aBlock[iNext].Off - (aBlock[i].Off+aBlock[i].Size); if (NumBytesBeforeBlock) { //如果两个毗邻的内存块之间存在间隙,整理之 U8* pData = &GUI_Heap.abHeap[aBlock[iNext].Off]; memmove(pData-NumBytesBeforeBlock, pData, aBlock[iNext].Size); aBlock[iNext].Off -=NumBytesBeforeBlock; } } } /* Check last block */ if (GUI_ALLOC_SIZE - (aBlock[i].Off+aBlock[i].Size) >= Size) {//没有超过内存上界,返回最后一个内存单元的目录索引, r = i; //aBlock[r].Off+aBlock[r].Size即空闲内存的起始地址 } return r; }
|