---------------------------------------------
-- 时间:2018-11-13
-- 创建人:Ruo_Xiao
-- 邮箱:xclsoftware@163.com
-- 若大神不吝抛砖,小菜感激不尽!
---------------------------------------------
一、OSMemMalloc
void* OSMemMalloc(uOSMemSize_t size)
{
// 变量初始化
//返回最终的已分配的内存块的首地址(不包括tOSMem_t)
uOS8_t * pResult = OS_NULL;
//gpOSMemBegin(堆)的迭代器
uOSMemSize_t ptr = 0U;
//分配完内存块之后剩余的空闲块的在堆中的位置,也是迭代器
uOSMemSize_t ptr2 = 0U;
//开始时是较大空闲块的首地址,由于堆分配是从低地址向高地址分配,分配完成之后,
//该地址变成了要分配的内存块的首地址,但是包含tOSMem_t,去掉tOSMem_t之后就是pResult。
tOSMem_t *ptOSMemTemp = OS_NULL;
//分配完内存块剩余的空闲块的首地址
tOSMem_t *ptOSMemTemp2 = OS_NULL;
// 初始化堆,详见:https://blog.csdn.net/itworld123/article/details/83998064
if(gpOSMemEnd==OS_NULL)
{
OSMemInit();
if(gpOSMemEnd==OS_NULL)
{
return pResult;
}
}
// 不需要分配则返回OS_NULL
if (size == 0)
{
return pResult;
}
// 对齐要分配的内存块
size = OSMEM_ALIGN_SIZE(size);
// 分配的内存块至少要大于OSMIN_SIZE_ALIGNED
if(size < OSMIN_SIZE_ALIGNED)
{
// every data block must be at least OSMIN_SIZE_ALIGNED long
size = OSMIN_SIZE_ALIGNED;
}
// 分配的内存块大小超过堆最大值,则返回OS_NULL
if (size > OSMEM_SIZE_ALIGNED)
{
return pResult;
}
// protect the heap from concurrent access
OSIntLock();
// 2018-11-10
// (uOSMemSize_t)((uOS8_t *)gpOSMemLFree - gpOSMemBegin) 确定闲置tOSMem_t首地址相对Begin的位置
// OSMEM_SIZE_ALIGNED - size 搜索的范围不能超过待分配内存块的最高地址处
// ptr = ((tOSMem_t *)(void *)&gpOSMemBegin[ptr])->NextMem 确定下一个tOSMem_t的位置
for (ptr = (uOSMemSize_t)((uOS8_t *)gpOSMemLFree - gpOSMemBegin); ptr < OSMEM_SIZE_ALIGNED - size;
ptr = ((tOSMem_t *)(void *)&gpOSMemBegin[ptr])->NextMem)
{
ptOSMemTemp = (tOSMem_t *)(void *)&gpOSMemBegin[ptr];
//1、ptOSMemTemp->Used 该内存块不能被用
//2、ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED)) >= size
// 计算该free指定的空闲块的大小,其中不包括tOSMem_t,故减掉 SIZEOF_OSMEM_ALIGNED
if ((!ptOSMemTemp->Used) && (ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED)) >= size)
{
// 分配内存的过程就是插入节点(tOSMem_t)的过程。
// ptOSMemTemp 当前节点的首地址(tOSMem_t)
// ptOSMemTemp->NextMem 下一个节点的首地址(tOSMem_t)
// ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED) 当前节点对应的内存块到下一个内存块对应的tOSMem_t首地址之间的大小
// (size + SIZEOF_OSMEM_ALIGNED + OSMIN_SIZE_ALIGNED) 申请内存完内存之后,在申请的内存后面插入新的tOSMem_t,
// tOSMem_t和下一个节点之间至少要有一个OSMIN_SIZE_ALIGNED大小的内存小块,否则两个tOSMem_t就连在
// 了一起。
// 如果满足上述要求,就插入一个节点,否则直接将该内存块设置为要申请的内存
if (ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED) >= (size + SIZEOF_OSMEM_ALIGNED + OSMIN_SIZE_ALIGNED))
{
ptr2 = ptr + SIZEOF_OSMEM_ALIGNED + size;
// 创建 ptOSMemTemp2 信息块,该信息块对应的内存块大小至少为 OSMIN_SIZE_ALIGNED
ptOSMemTemp2 = (tOSMem_t *)(void *)&gpOSMemBegin[ptr2];
ptOSMemTemp2->Used = 0;
ptOSMemTemp2->NextMem = ptOSMemTemp->NextMem;
ptOSMemTemp2->PrevMem = ptr;
ptOSMemTemp->NextMem = ptr2;
ptOSMemTemp->Used = 1;
if (ptOSMemTemp2->NextMem != OSMEM_SIZE_ALIGNED)
{
((tOSMem_t *)(void *)&gpOSMemBegin[ptOSMemTemp2->NextMem])->PrevMem = ptr2;
}
}
else
{
ptOSMemTemp->Used = 1;
}
//循环第一次,此时ptOSMemTemp=gpOSMemLFree。
if (ptOSMemTemp == gpOSMemLFree)
{
//若gpOSMemLFree完成了内存分配,即:Used为1,则更新Free指针。
while (gpOSMemLFree->Used && gpOSMemLFree != gpOSMemEnd)
{
gpOSMemLFree = (tOSMem_t *)(void *)&gpOSMemBegin[gpOSMemLFree->NextMem];
}
}
// 返回tOSMem_t对应的的内存块的地址
pResult = (uOS8_t *)ptOSMemTemp + SIZEOF_OSMEM_ALIGNED;
break;
}
}
OSIntUnlock();
return pResult;
}
二、OSMemCalloc
//Calloc和 Malloc的关系是,前者调用后者并且若申请内存块成功则初始化buffer。
//详见:https://blog.csdn.net/itworld123/article/details/79187109
void* OSMemCalloc(uOSMemSize_t count, uOSMemSize_t size)
{
void *pMem = OS_NULL;
// allocate 'count' objects of size 'size'
pMem = OSMemMalloc(count * size);
if (pMem)
{
// zero the memory
memset(pMem, 0, count * size);
}
return pMem;
}
注:建议将代码复制下来,用 VS Code 或者 Notepad++ 审阅效果更加。
(SAW:Game Over!)