一、简介
1. 功能
内存管理,是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且在适当的时候释放和回收内存资源。
2. 概念
内存管理的实现方法有很多种,他们其实最终都是要实现 2 个函数: malloc 和 free。
malloc 函数用于内存申请。
free 函数用于内存释放。
从上图可以看出,分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为 n块,对应的内存管理表,大小也为 n,内存管理表的每一个项对应内存池的一块内存。
内存管理表的项值代表的意义为:当该项值为 0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为 10,那么说明包括本项对应的内存块在内,总共分配了 10 个内存块给外部的某个指针。
内存分配方向如图所示,是从顶->底的分配方向。即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。
三、分配原理
当指针 p 调用 malloc 申请内存的时候,先判断 p 要分配的内存块数(m),然后从第 n 项开 始,向下查找,直到找到 m 块连续的空内存块(即对应内存管理表项为 0),然后将这 m 个内存管理表项的值都设置为 m(标记被占用),最后,把最后的这个空内存块的地址返回指针 p,完成一次分配。注意,如果当内存不够的时候(找到最后也没找到连续的 m 块空闲内存),则
返回 NULL 给 p,表示分配失败。
四、释放原理
当 p 申请的内存用完,需要释放的时候,调用 free 函数实现。 free 函数先判断 p 指向的内存地址所对应的内存块,然后找到对应的内存管理表项目,得到 p 所占用的内存块数目 m(内存管理表项目的值就是所分配内存块的数目),将这 m 个内存管理表项目的值都清零,标记释放,完成一次内存释放。
五、重要参数
内存的大小 = 内存池大小 + 内存管理表的大小
内存块(32个字节) 分割块( N ) = 内存池容量(字节)
( 内存管理表所占字节(U16 : 2个字节) 分割块(N)) = 内存管理表容量(字节)
一般情况下,内存块 和 内存池容量的值是知道的,是程序员根据硬件容量指定的。这里我们指定内存块为32字节,内存池容量为40K。
所以 分割块(N)= 内存池容量(字节) 内存块(32个字节)= 40K 32 = 40 1024 32 = 1280。
那 内存管理表容量(字节) = 2 分割块(N)= 2 (内存池容量(字节) 内存块(32个字节)) = 2 1280 = 2560。
定义两个内存,一个是内部内存(40K),一个是外部内存SRAM(960K).
内存管理参数:
内存池总大小:40K
内存管理状态表大小:1280 (U16) 数据块个数N
内存分块大小:32 字节
内存池总大小:960K
内存管理状态表大小:30720(U16) 数据块个数N
内存分块大小:32 字节
定义结构体:
struct _m_mallco_dev
{
u8 *membase[2]; //2个内存池 内部内存和外部内存的内存池
u16 *memmap[2]; //2个内存管理状态表
u8 memrdy[2]; //内存初始化标志
}
定义数组:
内存池:
__align(32) u8 mem1base[40960]; //40K 内存容量(字节) 32个字节一个块,块对齐
__align(32) u8 mem2base[983040] __attribute__((at(0x68000000))); //960K 内存容量(字节)
内存管理状态表:
u16 mem1mapbase[1280]; //内存表大小 40K / 32
u16 mem2mapbase[30720]; //内存表大小 960K / 32
定义的结构体指向定义的数组。
struct _m_mallco_dev mallco_dev=
{
mem1base,mem1base,
mem1mapbase,mem1mapbase,
0,0,
}
五、分配内存流程
1. 根据传进来的SIZE,确认需要分配几块内存块。比如说需要M块。
2. 在内存中,查找连续空闲的M块内存块,如果连续的空闲块不够M块,则向下一部分连续的空间进行查找。如果连续的空闲块个数有M块,则将这M块的内存管理状态表写上M,表示连续的M块内存,被使用了。
六、释放内存流程
1. 根据传进来的偏移量offset , 算出属于第几项L,然后读出L项的内存管理状态表的值R。
2. 将L项往后的L个内存管理状态值改为0。