转载请注明出处:http://blog.youkuaiyun.com/u011833609/article/details/47984403
与之前的单片机内存管理实现思路不同
此次新的内存管理是将整个待分配的内存块看作一个空闲内存描述结构加内存区域,申请一块内存是将空闲且大小合适的内存一分为二或整块获取来实现,释放内存是将当前内存与前后空闲内存合并完成的,有双向链表的意思。
memory.h文件
/***************************************************************************************************/
#ifndef __MEMORY_H__
#define __MEMORY_H__
#include "stm32f10x.h"
//创建一个内存区域
void DynMemCreate(void *pMem, uint32_t size);
//返回申请到的内存地址,若返回空,则申请失败
void *DynMemGet(uint32_t size);
//释放申请到的内存区域
void DynMemPut(void *pMem);
#endif //__MEMORY_H__
memory.c文件
#include "stdio.h"
#include "string.h"
#include "memory.h"
typedef enum
{
DYNMEM_FREE,
DYNMEM_USED,
}DYNMEM_USE_STATE;
typedef struct
{
DYNMEM_USE_STATE used;
uint32_t size;
void * pPrev;
void * pNext;
}DynMem_TypeDef;
static DynMem_TypeDef * pDynMem = NULL;
void DynMemCreate(void *pMem, uint32_t size)
{
if(NULL == pMem)
return;
if(size <= sizeof(DynMem_TypeDef))
return ;
pDynMem = pMem;
pDynMem->used = DYNMEM_FREE;
pDynMem->size = size - sizeof(DynMem_TypeDef);
pDynMem->pPrev = NULL;
pDynMem->pNext = NULL;
}
//若返回空,则申请失败
void *DynMemGet(uint32_t size)
{
DynMem_TypeDef * pGet = pDynMem;
DynMem_TypeDef * pFree = NULL;
if(size == 0)
return NULL;
size = (size + 3) / 4 * 4;
while(pGet != NULL)
{//找到合适空间
if((pGet->used != DYNMEM_FREE) || (pGet->size < size))
{
pGet = pGet->pNext;
continue;
}
//找到空闲且大小合适的内存区域
if(pGet->size - size > sizeof(DynMem_TypeDef))
{//可以放下一个新的内存块表,将其一分为二
pFree = (DynMem_TypeDef*)((uint32_t)pGet + sizeof(DynMem_TypeDef) + size);
/*修改链表关系*/
/*Step 1*/
pFree->pPrev = pGet;
/*Step 2*/
pFree->pNext = pGet->pNext;
/*Step 3*/
pGet->pNext = pFree;
/*Step 4*/
if(NULL != pFree->pNext)
{
(*(DynMem_TypeDef*)(pFree->pNext)).pPrev = pFree;
}
/*剩余空间配置*/
pFree->used = DYNMEM_FREE;
pFree->size = pGet->size - size - sizeof(DynMem_TypeDef);
/*获取到的空间配置*/
pGet->used = DYNMEM_USED;
pGet->size = size;
}
else
{//已经放不下一个新的内存块表,将其全部占有
pGet->used = DYNMEM_USED;
}
return (void*)((uint32_t)pGet + sizeof(DynMem_TypeDef));
}
return NULL;
}
void DynMemPut(void *pMem)
{
DynMem_TypeDef * pPut = NULL;
if(NULL == pMem)
return;
pPut = (DynMem_TypeDef*)((uint32_t)pMem - sizeof(DynMem_TypeDef));
pPut->used = DYNMEM_FREE;
//释放空间,整体释放/合二为一/合三为一
if((pPut->pPrev != NULL) && (((DynMem_TypeDef*)(pPut->pPrev))->used == DYNMEM_FREE))
{
((DynMem_TypeDef*)(pPut->pPrev))->size += sizeof(DynMem_TypeDef) + pPut->size;
((DynMem_TypeDef*)(pPut->pPrev))->pNext = pPut->pNext;
if(pPut->pNext != NULL)
{
((DynMem_TypeDef*)(pPut->pNext))->pPrev = pPut->pPrev;
}
pPut = (DynMem_TypeDef*)(pPut->pPrev);
}
if((pPut->pNext != NULL) && (((DynMem_TypeDef*)(pPut->pNext))->used == DYNMEM_FREE))
{
pPut->size += sizeof(DynMem_TypeDef) + ((DynMem_TypeDef*)(pPut->pNext))->size;
pPut->pNext = ((DynMem_TypeDef*)(pPut->pNext))->pNext;
if(pPut->pNext != NULL)
{
((DynMem_TypeDef*)(pPut->pNext))->pPrev = pPut;
}
}
}
初步测试通过,未经过详细测试,如有Bug,尊听点评。