初中生
最后登录1970-1-1
在线时间 小时
注册时间2017-2-24
|
楼主 |
发表于 2017-2-28 00:06:41
|
显示全部楼层
本帖最后由 时飞大师兄 于 2017-2-28 07:13 编辑
描述完毕“内存管理”的整个轮廓之后,我们来查看具体的内存管理函数是怎么实现的;
首先我们查看一下内存初始化函数OSMemInit,这个函数很简单,主要为全局变量gpOSMemBegin,gpOSMemEnd与gpOSMemLFree分配初始数值;
- /*****************************************************************************
- Function : OSMemInit
- Description : Zero the heap and initialize start, end and lowest-free pointer.
- Input : None
- Output : None
- Return : None
- *****************************************************************************/
- void OSMemInit(void)
- {
- tOSMem_t *ptOSMemTemp;
- // align the heap
- gpOSMemBegin = (uOS8_t *)OSMEM_ALIGN_ADDR(OSRAM_HEAP_POINTER);
-
- // initialize the start of the heap
- ptOSMemTemp = (tOSMem_t *)(void *)gpOSMemBegin;
- ptOSMemTemp->NextMem = OSMEM_SIZE_ALIGNED;
- ptOSMemTemp->PrevMem = 0;
- ptOSMemTemp->Used = 0;
-
- // initialize the end of the heap
- gpOSMemEnd = (tOSMem_t *)(void *)&gpOSMemBegin[OSMEM_SIZE_ALIGNED];
- gpOSMemEnd->Used = 1;
- gpOSMemEnd->NextMem = OSMEM_SIZE_ALIGNED;
- gpOSMemEnd->PrevMem = OSMEM_SIZE_ALIGNED;
- // initialize the lowest-free pointer to the start of the heap
- gpOSMemLFree = (tOSMem_t *)(void *)gpOSMemBegin;
- }
复制代码
接着是内存分配函数。
- /*****************************************************************************
- Function : OSMemMalloc
- Description : Allocate a block of memory with a minimum of 'size' bytes.
- Input : size -- the minimum size of the requested block in bytes.
- Output : None
- Return : pointer to allocated memory or OS_NULL if no free memory was found.
- the returned value will always be aligned (as defined by OSMEM_ALIGNMENT).
- *****************************************************************************/
- void* OSMemMalloc(uOSMemSize_t size)
- {
- uOS8_t * pResult = OS_NULL;
- uOSMemSize_t ptr, ptr2;
- tOSMem_t *ptOSMemTemp, *ptOSMemTemp2;
- if(gpOSMemEnd==OS_NULL)
- {
- OSMemInit();
- if(gpOSMemEnd==OS_NULL)
- {
- return pResult;
- }
- }
- if (size == 0)
- {
- return pResult;
- }
- // Expand the size of the allocated memory region so that we can
- // adjust for alignment.
- size = OSMEM_ALIGN_SIZE(size);
- if(size < OSMIN_SIZE_ALIGNED)
- {
- // every data block must be at least OSMIN_SIZE_ALIGNED long
- size = OSMIN_SIZE_ALIGNED;
- }
- if (size > OSMEM_SIZE_ALIGNED)
- {
- return pResult;
- }
- // protect the heap from concurrent access
- <font color="#000000"><span style="font-size: 15px; line-height: 22.5px;">OSIntLock</span></font>();
- // Scan through the heap searching for a free block that is big enough,
- // beginning with the lowest free block.
- 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];
- if ((!ptOSMemTemp->Used) && (ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED)) >= size)
- {
- // ptOSMemTemp is not Used and at least perfect fit is possible:
- // ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED) gives us the 'user data size' of ptOSMemTemp
- if (ptOSMemTemp->NextMem - (ptr + SIZEOF_OSMEM_ALIGNED) >= (size + SIZEOF_OSMEM_ALIGNED + OSMIN_SIZE_ALIGNED))
- {
- // (in addition to the above, we test if another tOSMem_t (SIZEOF_OSMEM_ALIGNED) containing
- // at least OSMIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'ptOSMemTemp')
- // -> split large block, create empty remainder,
- // remainder must be large enough to contain OSMIN_SIZE_ALIGNED data: if
- // ptOSMemTemp->NextMem - (ptr + (2*SIZEOF_OSMEM_ALIGNED)) == size,
- // tOSMem_t would fit in but no data between ptOSMemTemp2 and ptOSMemTemp2->NextMem
- ptr2 = ptr + SIZEOF_OSMEM_ALIGNED + size;
- // create ptOSMemTemp2 struct
- ptOSMemTemp2 = (tOSMem_t *)(void *)&gpOSMemBegin[ptr2];
- ptOSMemTemp2->Used = 0;
- ptOSMemTemp2->NextMem = ptOSMemTemp->NextMem;
- ptOSMemTemp2->PrevMem = ptr;
- // and insert it between ptOSMemTemp and ptOSMemTemp->NextMem
- ptOSMemTemp->NextMem = ptr2;
- ptOSMemTemp->Used = 1;
- if (ptOSMemTemp2->NextMem != OSMEM_SIZE_ALIGNED)
- {
- ((tOSMem_t *)(void *)&gpOSMemBegin[ptOSMemTemp2->NextMem])->PrevMem = ptr2;
- }
- }
- else
- {
- // (a ptOSMemTemp2 struct does no fit into the user data space of ptOSMemTemp and ptOSMemTemp->NextMem will always
- // be Used at this point: if not we have 2 unused structs in a row, OSMemCombine should have
- // take care of this).
- // -> near fit or excact fit: do not split, no ptOSMemTemp2 creation
- // also can't move ptOSMemTemp->NextMem directly behind ptOSMemTemp, since ptOSMemTemp->NextMem
- // will always be Used at this point!
- ptOSMemTemp->Used = 1;
- }
- if (ptOSMemTemp == gpOSMemLFree)
- {
- // Find next free block after ptOSMemTemp and update lowest free pointer
- while (gpOSMemLFree->Used && gpOSMemLFree != gpOSMemEnd)
- {
- gpOSMemLFree = (tOSMem_t *)(void *)&gpOSMemBegin[gpOSMemLFree->NextMem];
- }
- }
- pResult = (uOS8_t *)ptOSMemTemp + SIZEOF_OSMEM_ALIGNED;
- break;
- }
- }
- OSIntUnlock();
- return pResult;
- }
复制代码
内存释放函数。
- /*****************************************************************************
- Function : OSMemFree
- Description : Put a tOSMem_t back on the heap.
- Input : pMem -- the data portion of a tOSMem_t as returned by a previous
- call to OSMemMalloc()
- Output : None
- Return : None
- *****************************************************************************/
- void OSMemFree(void *pMem)
- {
- tOSMem_t *ptOSMemTemp;
- if (pMem == OS_NULL)
- {
- return;
- }
- if ((uOS8_t *)pMem < (uOS8_t *)gpOSMemBegin || (uOS8_t *)pMem >= (uOS8_t *)gpOSMemEnd)
- {
- return;
- }
-
- // protect the heap from concurrent access
- OSIntLock();
- // Get the corresponding tOSMem_t ...
- ptOSMemTemp = (tOSMem_t *)(void *)((uOS8_t *)pMem - SIZEOF_OSMEM_ALIGNED);
-
- //ptOSMemTemp->Used must be 1
- if( ptOSMemTemp->Used==1 )
- {
- // now set it unused.
- ptOSMemTemp->Used = 0;
- if (ptOSMemTemp < gpOSMemLFree)
- {
- // the newly freed struct is now the lowest
- gpOSMemLFree = ptOSMemTemp;
- }
- // finally, see if prev or next are free also
- OSMemCombine(ptOSMemTemp);
- }
- OSIntUnlock();
-
- return;
- }
复制代码
代码已经更新到Github上了,感兴趣的朋友请移步到Github查看更多源代码。
到现在,我们已经实现了上面提到的内存管理方面的第3和第4两项要求了。这样,嵌入式实时操作系统AIOS的内存管理已经基本实现了;
由于大部分的微控制器芯片资源非常有限,部分嵌入式操作系统在设计时没有单独的内存管理模块,而是在使用时临时分配。例如ucos嵌入式操作系统,在创建任务时,总是通过一个数组的形式分配一段内存空间,然后把数组的首地址及长度传递给待创建的任务使用。这样相当于把内存管理分散化,但是如果要整体设置系统的内存位置就不那么方便了。
|
|