⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memory.c

📁 Rabbit 32Bit RTOS源代码
💻 C
字号:
/*********************************************************************
*                   Copyright (c) 2011-2012,李士伟
*                     All rights reserved.
*文 件 名:memory.c
*描    述:可变分区内存管理,最先适应算法
*当前版本:V1.00
*作    者:李士伟
*创建日期:2011.09.29
**********************************************************************/
#include <mm\memory.h>
#include <kernel\asm.h>

INT32U              OSMemBase[OS_MEM_SIZE];  /* 配置内存 */
OSMEMFreeBlkHead   *OSMemFreeList;

OSMEMInf __OSMemInf; /* 内存信息 */

/*********************************************************************
*函 数 名:OS_InitMem
*描    述:初始化内存,及相关的内存管理全局变量
*输入参数:无
*输出参数:无
*返 回 值:无
*注    意:
**********************************************************************/
void OS_InitMem(void)
{
    
    OS_ENTER_CRITICAL();
    OSMemFreeList = (OSMEMFreeBlkHead *)(((INT32U)OSMemBase + sizeof(INT32U)-1) 
                    & (~(sizeof(INT32U)-1)));  /* 内存基址字对齐 */

    OSMemFreeList->BlkNext = NULL;

    /* 因内存基址字对齐处理,须重新计算内存大小*/
    OSMemFreeList->BlkSize = ((OS_MEM_SIZE << 2) - 
    ((INT32U)OSMemFreeList - (INT32U)OSMemBase)+sizeof(INT32U)-1) 
                           & (~(sizeof(INT32U) - 1));

    OSMemFreeList->BlkPrev = NULL;
    
    /* 初始化内存信息 */
    __OSMemInf.Usage = 0;
    __OSMemInf.TotalSize = OSMemFreeList->BlkSize;
    __OSMemInf.FreeSize = __OSMemInf.TotalSize;
    __OSMemInf.FreeBlks = 1;
    __OSMemInf.UsingBlks =0;

    OS_EXIT_CRITICAL();
}
/*********************************************************************
*函 数 名:API_GetMemInf
*描    述:获取内存使用信息
*输入参数:无
*输出参数:pMemInf 内存信息结构指针,内存使用信息写入指针指向结构体
*返 回 值:无
*注    意:
**********************************************************************/
void API_GetMemInf(OSMEMInf *pMemInf)
{
    OS_ENTER_CRITICAL();
    __OSMemInf.Usage = ((__OSMemInf.TotalSize - __OSMemInf.FreeSize) * 100)
                       / __OSMemInf.TotalSize;

    *pMemInf = __OSMemInf;

    OS_EXIT_CRITICAL();

}

/*********************************************************************
*函 数 名:malloc
*描    述:以字为单位分配内存块
*输入参数:size: 分配内存块的字节数,若分配的字节数非字的倍数,
*                会多分配1~3个字节凑齐字的倍数
*输出参数:无
*返 回 值:分配的内存块指针,用户要保证使用相同的指针值释放内存
*注    意:size 的值不能取0
**********************************************************************/
void* malloc(INT32U size)
{
    OSMEMFreeBlkHead *pblk;
    OSMEMUsingBlkHead *pUseblk;

    /* 按字分配内存,计算需分配的内存块大小(单位字) */

    size  = (size + sizeof(OSMEMUsingBlkHead) + sizeof(INT32U) -1)
            & (~(sizeof(INT32U) - 1));

    OS_ENTER_CRITICAL();
    pblk  = OSMemFreeList;

    /* 查找足够大的内存块 */
    while (pblk != NULL)
    {
        if (pblk->BlkSize >= size)
        {
            break;
        }
        pblk = pblk->BlkNext;
    }

    /* 找到足够大的内存块 */
    if (pblk != NULL)
    {    
         /* 分配整块内存块出去 */
        if ((pblk->BlkSize) < (size + sizeof(OSMEMFreeBlkHead))) 
        {
            if (pblk->BlkNext != NULL)
            {
                (pblk->BlkNext)->BlkPrev = pblk->BlkPrev;
            }

            if (pblk->BlkPrev != NULL) /* pblk 不是双向链表头节点 */
            {
                (pblk->BlkPrev)->BlkNext = pblk->BlkNext;
            }
            else  /* pblk 是双向链表头节点 */
            {
                OSMemFreeList = pblk->BlkNext;
            }

            size    = pblk->BlkSize;
            pUseblk = (OSMEMUsingBlkHead *)pblk;

            __OSMemInf.FreeBlks--; /* 空闲内块数量减1 */

        }
        else  /* 从内存块高端地址切分一块内存 */
        {
            pblk->BlkSize = pblk->BlkSize - size;
            pUseblk = (OSMEMUsingBlkHead *)
                     ((INT32U)pblk + (pblk->BlkSize));
        }

        pUseblk->SizeChk = size;
        pUseblk->Size    = size;

        __OSMemInf.FreeSize = __OSMemInf.FreeSize - size;
        __OSMemInf.UsingBlks++;

        OS_EXIT_CRITICAL();
        return (void *)((INT32U)pUseblk + sizeof(OSMEMUsingBlkHead));
    }
    /* 未找到足够大的内存块 */
    OS_EXIT_CRITICAL();
    return NULL;
}

/*********************************************************************
*函 数 名:OS_FreeMemErr
*描    述:释放内存校验出错处理
*输入参数:ptr: 释放内存块的指针
*输出参数:无
*返 回 值:无
*注    意:这个函数只是在内存释放出错时简单的重启系统
**********************************************************************/
void OS_FreeMemErr(void *ptr)
{

    Reboot();  /* 重启系统 */

}

/*********************************************************************
*函 数 名:free
*描    述:释放内存
*输入参数:ptr: 内存块指针
*输出参数:无
*返 回 值:无
*注    意:
**********************************************************************/
void free(void *ptr)
{
    OSMEMFreeBlkHead *pFreeblk;
    OSMEMUsingBlkHead *pUseblk;
    INT32U size;

    pUseblk =(OSMEMUsingBlkHead *)((INT32U)ptr - sizeof(OSMEMUsingBlkHead));

    OS_ENTER_CRITICAL();

    if (pUseblk->SizeChk != pUseblk->Size) /* 内存释放大小校验出错 */
    {
        OS_FreeMemErr(ptr);
        return;
    }

    size = pUseblk->Size;

    __OSMemInf.FreeSize +=size;
    __OSMemInf.UsingBlks--; /* 使用内存块计数减1 */

    pFreeblk = OSMemFreeList;

    if (pFreeblk == NULL)
    {

        OSMemFreeList = (OSMEMFreeBlkHead *)pUseblk;
        OSMemFreeList->BlkNext = NULL;
        OSMemFreeList->BlkSize = size;
        OSMemFreeList->BlkPrev = NULL;

        __OSMemInf.FreeBlks++;  /* 空闲内存块计数加1 */

        OS_EXIT_CRITICAL();
        return ;
    }

    while (pFreeblk !=NULL)
    {
        /* 链表中存在高于释放内存块首址的节点 */
        if ((INT32U)pUseblk < (INT32U)pFreeblk)
        {
            if (pFreeblk->BlkPrev == NULL)
            {
                /* pFreeblk是双向链表的头节点 */
                OSMemFreeList = (OSMEMFreeBlkHead *)pUseblk;
                OSMemFreeList->BlkNext = pFreeblk;
                OSMemFreeList->BlkSize = size;
                OSMemFreeList->BlkPrev = NULL;
                pFreeblk->BlkPrev = OSMemFreeList;
                
                __OSMemInf.FreeBlks++;  /*空闲内存块计数加1 */

                /* pFreeblk 指向释放的内存块节点,
                   在后面判断是否与下一块内存合并*/
                pFreeblk = OSMemFreeList;

            }
            else
            {

                pFreeblk = pFreeblk->BlkPrev;
                if ((INT32U)pUseblk == (INT32U)pFreeblk
                                    + (pFreeblk->BlkSize))
                {
                    /* 与上一个内存块相邻则合并 */
                    pFreeblk->BlkSize += size;
                }
                else
                {
                    /* 在双向链表中创建一个新内存块节点 */
                    ((OSMEMFreeBlkHead *)pUseblk)->BlkNext = pFreeblk->BlkNext;
                    ((OSMEMFreeBlkHead *)pUseblk)->BlkSize = size;
                    ((OSMEMFreeBlkHead *)pUseblk)->BlkPrev = pFreeblk;
                    (pFreeblk->BlkNext)->BlkPrev = (OSMEMFreeBlkHead *)pUseblk;
                     pFreeblk->BlkNext = (OSMEMFreeBlkHead *)pUseblk;
                    __OSMemInf.FreeBlks++;  /*空闲内存块计数加1 */
                     /* pFreeblk 指向释放的内存块节点,
                        在后面判断是否与下一块内存合并*/
                     pFreeblk = pFreeblk->BlkNext;

                }
            }

            /* 判断是否与存在的下一个内存块相邻 */
            if (pFreeblk->BlkNext !=NULL)
            {
                /* 与下一个内存块相邻则合并 */
                if ((INT32U)(pFreeblk->BlkNext) == (INT32U)pFreeblk 
                                + (pFreeblk->BlkSize))
                {
                    pFreeblk->BlkSize +=(pFreeblk->BlkNext)->BlkSize;
                    pFreeblk->BlkNext = (pFreeblk->BlkNext)->BlkNext;
                    if (pFreeblk->BlkNext != NULL)
                    {
                        (pFreeblk->BlkNext)->BlkPrev = pFreeblk;
                    }
                    
                    __OSMemInf.FreeBlks--;  /*空闲内存块计数减1 */
                }
            }

            OS_EXIT_CRITICAL();
            return ;
        }

        /* 释放的内存块首址高于双向链表最后一块内存首址 */
        if (pFreeblk->BlkNext == NULL)
        {
            if ((INT32U)pUseblk == (INT32U)pFreeblk + (pFreeblk->BlkSize))
            {
                /* 与上一个内存块相邻则合并 */
                pFreeblk->BlkSize += size;
            }
            else
            {
                pFreeblk->BlkNext = (OSMEMFreeBlkHead *)pUseblk;
               (pFreeblk->BlkNext)->BlkNext = NULL;
               (pFreeblk->BlkNext)->BlkSize = size;
               (pFreeblk->BlkNext)->BlkPrev = pFreeblk;
                __OSMemInf.FreeBlks++;  /*空闲内存块计数加1 */
            }
            OS_EXIT_CRITICAL();
            return ;
        }
        pFreeblk = pFreeblk->BlkNext;
    }

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -