Tiniux 3.0 / Memory.c / OSMemInit

---------------------------------------------
-- 时间:2018-11-04
-- 创建人:Ruo_Xiao
-- 邮箱:xclsoftware@163.com
---------------------------------------------

一、前言

1、本博文是我自己的理解,在没有把握的地方我会特别注明。本人菜鸟一枚,真诚地期待大神地指教!

2、Tiniux 3.0下载地址

3、建议使用Source Inlight看源码,效率更高!

4、为了避免篇幅过长,博文源码中使用的一些数据类型就不多解释了,本文只针对终点区域做详解。

5、根据Memory.h头文件可知,函数一共5个,如下:

uOSBase_t  OSMemInit(void);
void *OSMemMalloc(uOSMemSize_t size);
void *OSMemCalloc(uOSMemSize_t count, uOSMemSize_t size);

void *OSMemTrim(void *pMem, uOSMemSize_t size);
void  OSMemFree(void *pMem);

二、OSMemInit

1、源码

/***************************************************************************** 
Function    : OSMemInit 
Description : Zero the heap and initialize start, end and lowest-free pointer.
Input       : None
Output      : None 
Return      : None 
*****************************************************************************/
uOSBase_t OSMemInit(void)
{
    tOSMem_t *ptOSMemTemp = OS_NULL;

    // align the heap 
    gpOSMemBegin = (uOS8_t *)OSMEM_ALIGN_ADDR(OSRAM_HEAP_POINTER);

    /* Initialize the stack tiniux used. */
    memset(gpOSMemBegin, 0U, OSMEM_SIZE_ALIGNED);

    // initialize the start of the heap 
    ptOSMemTemp = (tOSMem_t *)(void *)gpOSMemBegin;
    ptOSMemTemp->NextMem = OSMEM_SIZE_ALIGNED;
    ptOSMemTemp->PrevMem = 0;
    ptOSMemTemp->Used = 0;
    
    // initialize the end of the heap 
    gpOSMemEnd = (tOSMem_t *)(void *)&gpOSMemBegin[OSMEM_SIZE_ALIGNED];
    gpOSMemEnd->Used = 1;
    gpOSMemEnd->NextMem = OSMEM_SIZE_ALIGNED;
    gpOSMemEnd->PrevMem = OSMEM_SIZE_ALIGNED;

    // initialize the lowest-free pointer to the start of the heap 
    gpOSMemLFree = (tOSMem_t *)(void *)gpOSMemBegin;
    
    return 0U;
}

2、该函数的目的:

(1)将申请的堆初始化为0;

(2)设置指向堆开始位置的tOSMem_t结构体;

(3)设置指向堆结束位置和指向最低位置的已经释放内存的首地址的tOSMem_t结构体。

3、系统内存分布

gpOSMemEnd - gpOSMemBegin OSMEM_SIZE_ALIGNED

4、tOSMem_t

typedef struct _tOSMem 
{
  uOSMemSize_t NextMem;   
  uOSMemSize_t PrevMem;    
  uOS8_t Used;     
}tOSMem_t;

(1)作用:用于记录堆中已分配的和未分配的内存块在系统内存中的位置(首地址)。

(2)NextMem:中,下一个tOSMem_t的首地址。

(3)PrevMem:中,上一个tOSMem_t的首地址。

(4)Used:指明其后面的内存块是否被分配,0则为分配,非0则已分配。

(5)注意:tOSMem_t中的元素指明的地址是中的地址,gpOSMemBegingpOSMemEnd 和 gpOSMemLFree首地址都是系统内存中的地址。

5、在系统内存中申请堆

gpOSMemBegin = (uOS8_t *)OSMEM_ALIGN_ADDR(OSRAM_HEAP_POINTER);

(1)OSMEM_ALIGN_ADDR,地址对齐操作。

(2)OSRAM_HEAP_POINTER,堆数组的首地址。

#define OSMEM_SIZE_ALIGNED        OSMEM_ALIGN_SIZE(512)
uOS8_t OSRamHeap[OSMEM_SIZE_ALIGNED + (2U*SIZEOF_OSMEM_ALIGNED) + OSMEM_ALIGNMENT];
#define OSRAM_HEAP_POINTER OSRamHeap

A、上述代码的作用是申请512个字节的堆,但是为了在堆中包含两个tOSMem_t(gpOSMemEnd 和 gpOSMemLFree)同时为了数据对齐,则加上了(2U*SIZEOF_OSMEM_ALIGNED) + OSMEM_ALIGNMENT

B、特别声明:该数组类型为unsigned char,故1个字节即为1个元素,两个tOSMem_t首地址之间的差值就是二者在gpOSMemBegin数组中位置之间的差值。

6、对于刚刚分配好的堆,实际上就2个内存块,一个是ptOSMemTemp信息块和其对应的内存块,另一个是gpOSMemEnd信息块,如下图所示:

1、由于就两个内存块,故:ptOSMemTemp -> NextMem  = OSMEM_SIZE_ALIGNED

由于ptOSMemTemp之前没有节点,故:ptOSMemTemp -> PrevMem  = 0

同时由于该内存块没有分配,故:ptOSMemTemp -> Used = 0

2、由于gpOSMemEnd的作用是作为堆的尾端,故: gpOSMemEnd -> Used = 1。

同时为了不让其参加运算,孤立它,故:   

gpOSMemEnd -> NextMem = OSMEM_SIZE_ALIGNED;
gpOSMemEnd -> PrevMem = OSMEM_SIZE_ALIGNED;

 

三、拓展

解决了delete []ptr,在delete不知道该ptr数组大小的时候就准确地释放了内存的问题。原因就是在每一个已分配的内存块的前面都添加了相应的信息块,用于存放该存储块首尾在系统内存中的位置,如Tiniux中的tOSMem_t

 

 

(SAW:Game Over!)

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值