这是个人编写的第三版内存管理器,主要用在单片机上。这一系列的内存管理器,由于本人对内存碎片的执念,于是前两版的使用非常反人类。举个例子:
第一版
void** malloc(uint32_t _size,uint8 _userid);
分配出来的是指向地址的地址,这对常规程序来说,用起来的感觉是相当酸爽。
第二版
void* malloc(uint32_t _size,uint8_t _userid,void **_address);
这就比较好看点了,但是还要给一个被分配的指针变量的地址。(内存管理第二版)
上面两个版本,用的一种思路是——知道被分配的地址a的地址b,每当碎片整理时,直接将数据移动到上一块被使用的内存后面,更新地址b上的地址a,得到地址c。
碎片整理前
类型 | 内存块1 | 内存块2 | 内存块3 | 内存块4 | 内存块5 | 内存块6 |
---|---|---|---|---|---|---|
数据 | hello | world | !!! | |||
内存池地址 | 0x40000000 | 0x40000010 | 0x40000020 | 0x40000030 | 0x40000040 | 0x40000050 |
被分配的地址 | 0x20001024 | 0x20003280 | 0x20007238 |
碎片整理后
类型 | 内存块1 | 内存块2 | 内存块3 | 内存块4 | 内存块5 | 内存块6 |
---|---|---|---|---|---|---|
数据 | hello | world | !!! | |||
内存池地址 | 0x40000000 | 0x40000010 | 0x40000020 | 0x40000030 | 0x40000040 | 0x40000050 |
被分配的地址 | 0x20001024 | 0x20003280 | 0x20007238 |
将内存块 0x40000020 上的数据 “world” 复制到 内存块 0x40000010 上,并将新的地址更新到指针变量地址 0x20003280 上。
像这样做的优点是,当碎片整理完成后,不影响数据的使用。而缺点是,只能自己玩,并不适合一起用。
但是在某一天,翻资料,看到了linux的内存管理机制后,一下顿悟了,于是有了内存管理器的第三版。
原理
(n块内存组成一页,n页内存组成一组,n组内存)
1. 根据设定的内存大小(不超过物理内存)即内存池,分配 x 组(目前x最大值为1024),根据分配策略限定每组内存大小。
2. 按照 2i,i∈[0,x] 2 i , i ∈ [ 0 , x ] 的规律,对 i,i∈[0,x] i , i ∈ [ 0 , x ] 组进行分页。
3. 内存分配顺序,由小页到大页,游大端到大端。
4. 当要分配的