microMem

存储结构示意图:

 

 

代码:

/*
 *  modifier: Honrun
 *  date:     2021/12/21 20:42
 */
#include "stdio.h"
#include "stdint.h"
#include "DevicesMem.h"


MemType g_typeMemHead = {0};
/* 需要增加 sizeof(MemType) * 2 个长度,以使字节对齐,以及存储管理信息 */
static uint8_t st_MemHeap[DEVICES_MEM_LENGTH + sizeof(MemType) * 2] = {0};


void vMemInit(void)
{
    vMemCreate(&g_typeMemHead, st_MemHeap, DEVICES_MEM_LENGTH);
}

static int8_t cMemSet(void *pvMemAddr, int32_t iValue, int32_t iSize)
{
    uint32_t *puiData = pvMemAddr;

    if((pvMemAddr == NULL) || (iSize < 0))
        return -1;

    iSize /= 4;
    while((iSize--) > 0)
    {
        *puiData++ = iValue;
    }

    return 0;
}

static void *pvMemCpy(void *pvMemTargetAddr, void *pvMemSourceAddr, int32_t iSize)
{
    uint32_t *puiTargetData = pvMemTargetAddr, *puiSourceData = pvMemSourceAddr;

    if((pvMemTargetAddr == NULL) || (pvMemSourceAddr == NULL) || (iSize < 0))
        return NULL;

    iSize /= 4;
    while((iSize--) > 0)
    {
        *puiTargetData++ = *puiSourceData++;
    }

    return pvMemTargetAddr;
}

void vMemCreate(MemType *ptypeMemHanle, uint8_t *pucMemHeap, int32_t iLength)
{
    MemType *ptypeMemNow = NULL;

    /* 地址 N 字节对齐 */
    ptypeMemHanle->startAddr = memRoundUp((uint32_t)(pucMemHeap), MEM_ROUNDUP_VALUE);
    ptypeMemHanle->stopAddr  = ptypeMemHanle->startAddr + iLength;
    ptypeMemHanle->state     = MEM_UNUSED;

    /* 初始化第一个空闲空间 */
    ptypeMemNow  = (MemType *)ptypeMemHanle->startAddr;
    *ptypeMemNow = *ptypeMemHanle;

    /* 初始化内存空间末尾的管理信息,标志为已使用是为了在遍历时方便判断退出,以及方便free函数判断 */
    ptypeMemNow  = (MemType *)ptypeMemHanle->stopAddr;
    *ptypeMemNow = *ptypeMemHanle;
    ptypeMemNow->state = MEM_USED;
}

void *pvMemMalloc(MemType *ptypeMemHanle, int32_t iSize)
{
    void *pvHandle = NULL;
    MemType *ptypeMemNow = NULL, *ptypeMemNext = NULL, *ptypeMemMin = NULL;
    int32_t iAddrStop = 0, iSizeNow = 0, iSizeMin = 0x7FFFFFFF;

    if(iSize < 0)
        return NULL;

    /* 长度 N 字节对齐 */
    iSize = memRoundUp(iSize, MEM_ROUNDUP_VALUE);

    /* 遍历mem空间 */
    for(ptypeMemNow = (MemType *)ptypeMemHanle->startAddr; (int32_t)ptypeMemNow < ptypeMemHanle->stopAddr; ptypeMemNow = (MemType *)ptypeMemNow->stopAddr)
    {
        if(ptypeMemNow->state == MEM_UNUSED)
        {
            iSizeNow = ptypeMemNow->stopAddr - ptypeMemNow->startAddr - sizeof(MemType);

            /* 最小空闲匹配 */
            if((iSizeNow >= iSize) && (iSizeMin > iSizeNow))
            {
                iSizeMin = iSizeNow;
                ptypeMemMin = ptypeMemNow;

                /* 找到刚好相同大小的空闲空间就直接退出遍历 */
                if(iSizeMin == iSize)
                    break;
            }
        }
    }

    /* 没匹配到合适的最小空间,表示当前分配不了 */
    if(ptypeMemMin == NULL)
        return NULL;

    /* 标志为已使用 */
    ptypeMemMin->state = MEM_USED;

    /* 最小匹配空间被划分后还有剩余空间,并能够存储下一个头部信息 */
    if((iSizeMin - iSize) >= sizeof(MemType))
    {
        iAddrStop = ptypeMemMin->stopAddr;
        ptypeMemMin->stopAddr = ptypeMemMin->startAddr + sizeof(MemType) + iSize;

        ptypeMemNext = (MemType *)ptypeMemMin->stopAddr;
        ptypeMemNext->startAddr = ptypeMemMin->stopAddr;
        ptypeMemNext->stopAddr  = iAddrStop;
        ptypeMemNext->state     = MEM_UNUSED;
    }
    /* 扩容,不遗留用不上的小空闲空间 */
    else
    {
        ptypeMemMin->stopAddr = ptypeMemMin->startAddr + sizeof(MemType) + iSizeMin;
    }

    /* 返回空间管理信息之后的空间地址 */
    pvHandle = (void *)(ptypeMemMin->startAddr + sizeof(MemType));

    return pvHandle;
}

void *pvMemCalloc(MemType *ptypeMemHanle, int32_t iNumber, int32_t iSize)
{
    void *pvHandle = NULL;
    int32_t iSizeTemp = iNumber * iSize;

    /* 长度 N 字节对齐 */
    iSizeTemp = memRoundUp(iSizeTemp, MEM_ROUNDUP_VALUE);

    pvHandle = pvMemMalloc(ptypeMemHanle, iSizeTemp);

    if(pvHandle != NULL)
    {
        cMemSet(pvHandle, 0, iSizeTemp);
    }

    return pvHandle;
}

void *pvMemRealloc(MemType *ptypeMemHanle, void *pvMemAddr, int32_t iSize)
{
    void *pvHandle = NULL;
    MemType *ptypeMemOld = NULL, *ptypeMemNow = NULL, *ptypeMemNext = NULL;
    int32_t iAddrStart = 0, iNewSize = 0, iOldSize = 0;

    if(pvMemAddr == NULL)
        return NULL;

    /* 位移到头部管理信息位置 */
    iAddrStart = (int32_t)(pvMemAddr - sizeof(MemType));
    if((iAddrStart < ptypeMemHanle->startAddr) || (iAddrStart > ptypeMemHanle->stopAddr))
        return NULL;

    ptypeMemOld = (MemType *)(iAddrStart);

    /* 长度 N 字节对齐 */
    iSize = memRoundUp(iSize, MEM_ROUNDUP_VALUE);

    /* 计算后续衔接空闲空间的大小 */
    for(ptypeMemNow = (MemType *)ptypeMemOld->stopAddr; ptypeMemNow->state == MEM_UNUSED; ptypeMemNow = (MemType *)(ptypeMemNow->stopAddr));

    iNewSize = (int32_t)ptypeMemNow - ptypeMemOld->startAddr - sizeof(MemType);

    /* 直接拓展衔接的空闲空间 */
    if(iNewSize >= iSize)
    {
        /* 最小匹配空间被划分后还有剩余空间,并能够存储下一个头部信息 */
        if((iNewSize - iSize) >= sizeof(MemType))
        {
            ptypeMemOld->stopAddr = ptypeMemOld->startAddr + sizeof(MemType) + iSize;

            ptypeMemNext = (MemType *)ptypeMemOld->stopAddr;
            ptypeMemNext->startAddr = ptypeMemOld->stopAddr;
            ptypeMemNext->stopAddr  = (int32_t)ptypeMemNow;
            ptypeMemNext->state     = MEM_UNUSED;
        }
        /* 扩容,不遗留用不上的小空闲空间 */
        else
        {
            ptypeMemOld->stopAddr = ptypeMemOld->startAddr + sizeof(MemType) + iNewSize;
        }

        return pvMemAddr;
    }
    /* 重新分配空间 */
    else
    {
        /* 分配不到满足所需大小的空间 */
        if((pvHandle = pvMemMalloc(ptypeMemHanle, iSize)) == NULL)
            return NULL;

        /* 转移拷贝数据 */
        iOldSize = ptypeMemOld->stopAddr - ptypeMemOld->startAddr - sizeof(MemType);
        pvMemCpy(pvHandle, pvMemAddr, iOldSize);

        /* 释放旧空间 */
        vMemFree(ptypeMemHanle, pvMemAddr);

        return pvHandle;
    }
}

void vMemFree(MemType *ptypeMemHanle, void *pvMemAddr)
{
    MemType *ptypeMemNow = NULL, *ptypeMemPrev = NULL, *ptypeMemNext = NULL;
    int32_t iAddrStart = 0;

    if(pvMemAddr == NULL)
        return;

    /* 位移到头部管理信息位置 */
    iAddrStart = (int32_t)(pvMemAddr - sizeof(MemType));
    if((iAddrStart < ptypeMemHanle->startAddr) || (iAddrStart > ptypeMemHanle->stopAddr))
        return;

    ptypeMemNow = (MemType *)(iAddrStart);
    ptypeMemNow->state = MEM_UNUSED;

    /* 遍历,找到当前待删除空间的前面一个空间 */
    for(ptypeMemPrev = (MemType *)(ptypeMemHanle->startAddr); ptypeMemPrev->stopAddr < ptypeMemNow->startAddr; ptypeMemPrev = (MemType *)ptypeMemPrev->stopAddr);

    /* 合并前面一个相连的空闲空间 */
    if(ptypeMemPrev->state == MEM_UNUSED)
    {
        ptypeMemPrev->stopAddr = ptypeMemNow->stopAddr;
        ptypeMemNow = ptypeMemPrev;
    }

    /* 合并后面一个相连的空闲空间 */
    ptypeMemNext = (MemType *)ptypeMemNow->stopAddr;
    if(ptypeMemNext->state == MEM_UNUSED)
    {
        ptypeMemNow->stopAddr = ptypeMemNext->stopAddr;
    }
}

头文件:

#ifndef DEVICESMEM_H_INCLUDED
#define DEVICESMEM_H_INCLUDED

#include "stdint.h"


/* 字节对齐(至少要4字节对齐) */
#define MEM_ROUNDUP_VALUE   8
/* 使x对n字节对齐 */
#define memRoundUp(x, n) (((x) + (n) - 1) & (~((n) - 1)))

/* 此区域内存未使用 */
#define MEM_UNUSED  0
/* 此区域内存已使用 */
#define MEM_USED    1


/* 模拟动态内存大小 */
#define DEVICES_MEM_LENGTH          (1024 * 1)


typedef struct{
    int32_t startAddr: 30;
    int32_t stopAddr: 30;
    uint32_t state: 2;
}MemType;


/* 动态内存头部信息 */
extern MemType g_typeMemHead;


void vMemInit(void);
void vMemCreate(MemType *ptypeMemHanle, uint8_t *pucMemHeap, int32_t iLength);
void *pvMemMalloc(MemType *ptypeMemHanle, int32_t iSize);
void *pvMemCalloc(MemType *ptypeMemHanle, int32_t iNumber, int32_t iSize);
void *pvMemRealloc(MemType *ptypeMemHanle, void *pvMemAddr, int32_t iSize);
void vMemFree(MemType *ptypeMemHanle, void *pvMemAddr);

#endif // DEVICESMEM_H_INCLUDED

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值