STM32 一个简单的内存管理实现 支持4K对齐 和 回收合并

前言

看到一个简单的内存分配器, 移植过来放到自己的开发板, 想用这个主要是它比较小而且自己也容易看懂, 目前基本也够用了

基本数据结构定义

typedef unsigned int addr_t;  //地址类型定义

//可用内存描述
typedef struct
{
	unsigned int size;
	addr_t addr;
} freeinfo_t;

//内存管理器
typedef struct {
	int frees, maxfrees, lostsize, losts;
	freeinfo_t *free;
} memx_t;

管理方法定义

void memx_init(memx_t *man) {
	man->frees = 0;			  /* 剩余容量 */
	man->maxfrees = 0;		/* 统计:最大值 */
	man->lostsize = 0;		/* 释放失败的容量 */
	man->losts = 0;			  /* 释放失败的次数*/
	return;
};

unsigned int memx_total(memx_t *man) {
	unsigned int i, t = 0;
	for (i = 0; i < man->frees; i++) {
		t += man->free[i].size;
	}
	return t;
};

addr_t memx_alloc(memx_t *man, unsigned int size){
	unsigned int i;
	addr_t a;
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].size >= size) {
			/* 有足够容量 */
			a = man->free[i].addr;
			man->free[i].addr += size;
			man->free[i].size -= size;
			if (man->free[i].size == 0) {
				/* free里没有了, 那么向前移动 */
				man->frees--;
				for (; i < man->frees; i++) {
					man->free[i] = man->free[i + 1];
				}
			}
			return a;
		}
	}
	return 0; /* 没了返回0 */
};

int memx_free(memx_t *man, addr_t addr, unsigned int size) {
	int i, j;
	/* 查找放入的位置 */
	for (i = 0; i < man->frees; i++) {
		if (man->free[i].addr > addr) {
			break;
		}
	}

	if (i > 0) {
		/* 前面有的 */
		if (man->free[i - 1].addr + man->free[i - 1].size == addr) {
			/* 前面的空间可以合并 */
			man->free[i - 1].size += size;
			if (i < man->frees) {
				/* 后面有 */
				if (addr + size == man->free[i].addr) {
					/* 后面的也可以合并 */
					man->free[i - 1].size += man->free[i].size;
					/* free[i]删除, 向前移动下 */
					man->frees--;
					for (; i < man->frees; i++) {
						man->free[i] = man->free[i + 1]; 
					}
				}
			}
			return 0; /* 完成 */
		}
	}
	/* 前面合并不了 */
	if (i < man->frees) {
		/* 后面有的 */
		if (addr + size == man->free[i].addr) {
			/* 后面可以合并 */
			man->free[i].addr = addr;
			man->free[i].size += size;
			return 0; /* 成功 */
		}
	}
	/* 前后都没法合并 */
	if (man->frees < MEMMAN_FREES) {
		/* 后面的空间移动下, 制作间隙 */
		for (j = man->frees; j > i; j--) {
			man->free[j] = man->free[j - 1];
		}
		man->frees++;
		if (man->maxfrees < man->frees) {
			man->maxfrees = man->frees; /* 更新最大值 */
		}
		man->free[i].addr = addr;
		man->free[i].size = size;
		return 0; /* 成功结束 */
	}
	/* 没有空间移动了 */
	man->losts++;
	man->lostsize += size;
	return -1; /* 失败 */
}

定义自己包装函数库, 释放时自动处理size, 也可提高移植性

#define FREE_MAP_SIZE (MEMMAN_FREES * sizeof(freeinfo_t))

memx_t man;  //静态注册内存管理器

// 初始化函数, 启动时调用
void MEM_Init() {
	man.free = (freeinfo_t *)Bank1_SRAM3_ADDR;  // 初始化内存起始地址
	
	memx_init(&man); //初始化内存管理器
	memx_free(&man, (addr_t)Bank1_SRAM3_ADDR + FREE_MAP_SIZE, 1024 * 1024 - FREE_MAP_SIZE); // 释放内存, 需留出开始的一段给free数组
}

// 4K对齐的内存分配
void *MEM_Malloc4k(int size) {
	size = (size + 16 + 0xfff) & 0xfffff000;
	char *p = (char *)memx_alloc(&man, size); //申请
	if(p != 0) {
		*((int *)p) = size; //保存size
		p += 16;
	}
	return p; //返回地址
}

// 4K对齐的内存释放
void MEM_Free4k(void *p) {
	char *q = p;
	int size;
	if (q!=0) {
		q -= 16;
		size = *((int *)q); //取回size
		memx_free(&man, (addr_t)q, size); //释放
	}
}

// 申请内存
void *MEM_Malloc(int size) {
	char *p = (char *)memx_alloc(&man, size + 16);
	if(p != 0) {
		*((int *)p) = size;
		p += 16;
	}
	return p;
}

// 释放内存
void MEM_Free(void *p) {
	char *q = p;
	int size;
	if (q!=0) {
		q -= 16;
		size = *((int *)q);
		memx_free(&man, (addr_t)q, size + 16);
	}
}

// LCD 里显示剩余内存
void MEM_ShowFreeSize()
{
	char free_log[12];
	u32 total = memx_total(&man) / 1024;
	sprintf(free_log, "free:%uK", total);
	FRONT_COLOR=BLACK;
	//低于300K红色
	if(total < 300) {
		FRONT_COLOR=RED;
	}

	LCD_ShowString(245,460,200,16,16, (u8 *)free_log);//显示内存容量 
}

把一些较大的静态分配改到动态的SRAM里, 到底主内存较小, 最终效果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Potcutre

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值