两种内存池管理方法对比

 

一、问题背景

最近在调试ambiq apollo3的蓝牙时,其使用了ARM Cordio WSF的蓝牙协议栈。通过学习wsf_buf.c的实现,看到了一种不同于固定大小内存块的内存池管理方式。它使用了可变大小的内存块分配,支持内存块大小自定义。为了学习其内存管理思想,故特此记录下这两种内存池管理方式的差异。本文将分别介绍了这两种内存池管理方法的实现方式,最后对比两种方式的优缺点和适用场景。

 

二、两种内存池管理

2.1 固定大小内存块分配(参考正点原子STM32F4 malloc.c)

固定大小内存块的方式,简单的说就是将内存按照相同大小划分成若干个内存块。每一个内存块有一个对应的内存管理表。如果对应的内存管理表为0,则标志未使用。非零表示此内存已经被分配使用中。

分块式内存管理由内存池和内存管理表两部分组成。内存池被等分为 n块,对应的内存管理表,大小也为 n,内存管理表的每一个项对应内存池的一块内存。

内存管理表的项值代表的意义为:当该项值为 0 的时候,代表对应的内存块未被占用,当该项值非零的时候,代表该项对应的内存块已经被占用,其数值则代表被连续占用的内存块数。比如某项值为 10,那么说明包括本项对应的内存块在内,总共分配了 10 个内存块给外部的某个指针。

内寸分配方向如图所示,是从顶->底的分配方向。即首先从最末端开始找空内存。当内存管理刚初始化的时候,内存表全部清零,表示没有任何内存块被占用。

                       

                                                                                      图1 内存块物理上分布图

2.1.1 初始化

在移植这种内存池分配前,我们需要预先定义待分配的内存物理地址和内存块大小。如下所示,在STM32F4 MCU中我们有内部SRAM、内部CCRAM和外部SRAM,共三处内存。通过MEMx_BLOCK_SIZE定义内存块的大小,我们这里将这三处内存都设置为32byte。

MEMx_MAX_SIZE表示内存管理大小。而内存表由于和内存一一对应,故MEMx_MAX_SIZE/MEMx_BLOCK_SIZE就能得到实际的内存表大小(个数)。

//malloc.h 头文件定义:
//mem1内存参数设定.mem1完全处于内部SRAM里面.
#define MEM1_BLOCK_SIZE			32  	  		//内存块大小为32字节
#define MEM1_MAX_SIZE			20*1024  		//最大管理内存 100K
#define MEM1_ALLOC_TABLE_SIZE	MEM1_MAX_SIZE/MEM1_BLOCK_SIZE 	//内存表大小
		 
//mem2内存参数设定.mem2处于CCM,用于管理CCM(特别注意,这部分SRAM,仅CPU可以访问!!)
#define MEM2_BLOCK_SIZE			32  	  		//内存块大小为32字节
#define MEM2_MAX_SIZE			60 *1024  		//最大管理内存60K
#define MEM2_ALLOC_TABLE_SIZE	MEM2_MAX_SIZE/MEM2_BLOCK_SIZE 	//内存表大小

//mem3内存参数设定.mem3的内存池处于外部SRAM里面
#define MEM3_BLOCK_SIZE			32  	  		//内存块大小为32字节
#define MEM3_MAX_SIZE			960 *1024  		//最大管理内存960K
#define MEM3_ALLOC_TABLE_SIZE	MEM3_MAX_SIZE/MEM3_BLOCK_SIZE 	//内存表大小
		 

// malloc.c源码定义
//内存池(32字节对齐)
__align(32) u8 mem1base[MEM1_MAX_SIZE];					//内部SRAM内存池
__align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X10000000)));	//内部CCM内存池
__align(32) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X68000000)));	//外部SRAM内存池
//内存管理表
u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];							//内部SRAM内存池MAP
u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000+MEM2_MAX_SIZE)));	//内部CCM内存池MAP
u16 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM3_MAX_SIZE)));	//外部SRAM内存池MAP
//内存管理参数	   
const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE,MEM3_ALLOC_TABLE_SIZE};//内存表大小
const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE,MEM3_BLOCK_SIZE};//内存分块大小
const u32 memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE,MEM3_MAX_SIZE};	

初始化时,只用将内存池和内存管理表都清零即可。

//内存管理初始化  
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值