又一个简单而强大的单片机内存管理器-不带内存碎片整理

14 篇文章 0 订阅
8 篇文章 1 订阅

转载请注明出处:http://blog.csdn.net/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,尊听点评。






  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值