[连载]嵌入式实时操作系统TINIUX设计与实现 – 内存管理之实现篇

描述完毕“内存管理”的整个轮廓之后,我们来查看具体的内存管理函数是怎么实现的;


首先我们查看一下内存初始化函数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 
	OSIntLock();


	// 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嵌入式操作系统,在创建任务时,总是通过一个数组的形式分配一段内存空间,然后把数组的首地址及长度传递给待创建的任务使用。这样相当于把内存管理分散化,但是如果要整体设置系统的内存位置就不那么方便了。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值