📄 memory.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 + -