单片机上内存管理(重定义malloc & free)de实现
在单片机上经常会需要用到像标准c库中的内存分配,可是单片机并没有内存管理机制,如果直接调用库函数(malloc,free...),会导致内存碎片越用越多,很容易使系统崩溃掉,这里分享一个自己写的适用于单片机的内存分配方法,具备轻量级的内存管理能力,有效减少内存碎片,提高单片机系统工作稳定性。
如下图,heap_start开始的地方,是我们存放用户数据的地方,在heap_end之前都是大小固定的一个个内存管理块,内存管理块用于记录每次用户申请内存的地址、大小、释放情况。在malloc时,会优先选择和用户申请空间最相当的内存块,以减少内存碎片产生。在free的内存块时,如果遇到相邻内存块均为空闲块时,便会将几块相邻的内存块合并成一块,以减少内存碎片。
SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。
源码下载:
alloc.c
/* ******************************************************************************** * memory alloc * * (c) Copyright 2018-2020; * All rights reserved. Protected by international copyright laws. * * MEMORY ALLOC * * File : mem_alloc.c * By : Recahrd.Zhang * Version : V1.00 * ******************************************************************************** */ #include <string.h> #include "mem_alloc.h" #include "debug.h" #define MEM_ALLOC 1 #if defined (MEM_ALLOC)&&MEM_ALLOC #define alloc_printf printf #else #define alloc_printf(argv, ...) #endif #define MEM_SIZE 2*1024 /*内存池的大小 2 KBytes*/ static char mem[MEM_SIZE]; /*定义用来内存分配的数组*/ #define MEM_START &mem[0] /*定义内存池的首地址*/ #define MEM_END &mem[MEM_SIZE] /*定义内存池的尾地址*/ enum USE_STA{ /*定义内存块的使用状态(UNUSED 未使用),(USED 已使用)*/ UNUSED = 0, USED = 1 }; #pragma pack(1) typedef struct mem_block{ /*定义内存管理块的数据结构*/ void *mem_ptr; /*当前内存块的内存地址*/ struct mem_block *nxt_ptr; /*下一个内存管理块的地址*/ unsigned int mem_size; /*当前内存块的大小*/ enum USE_STA mem_sta; /*当前内存块的状态*/ }mem_block; #pragma pack() #define BLK_SIZE sizeof(mem_block) /*内存管理块的大小*/ #define HEAD_NODE (MEM_END - BLK_SIZE)/*头内存管理块的地址*/ static signed char mem_init_flag = -1; /*内存分配系统初始化的标志(-1 未初始化),(1 已初始化)*/ /* ******************************************************************************** * 内存分配系统初始化 * * 描述 : 初始化内存分配系统,为malloc和free做好准备工作。 * * 参数 : 无 * * 返回 : 无 ******************************************************************************** */ void mem_init(void) { mem_block *node; memset(mem, 0x00UL, sizeof(mem)); node = (mem_block *)HEAD_NODE; node->mem_ptr = MEM_START; node->nxt_ptr = (mem_block *)HEAD_NODE; node->mem_size = MEM_SIZE - BLK_SIZE; node->mem_sta = UNUSED; mem_init_flag = 1; } /* ******************************************************************************** * 内存申请函数 * * 描述 : 内存申请函数 * * 参数 : nbytes 要申请的内存的字节数。 * * 返回 : 成功 返回申请到的内存的首地址 * 失败 返回NULL ******************************************************************************** */ static void *malloc(unsigned nbytes) { unsigned int suit_size = 0xFFFFFFFFUL; mem_block *head_node=NULL, *tmp_node=NULL, *suit_node=NULL; if(nbytes == 0) { alloc_printf("参数非法!\r\n"); return NULL; } if(mem_init_flag < 0) { alloc_printf("未初始化,先初始化.\r\n"); mem_init(); } head_node = tmp_node = (mem_block *)HEAD_NODE; while(1) { if(tmp_node->mem_sta == UNUSED) { if(nbytes <= tmp_node->mem_size && tmp_node->mem_size < suit_size) { suit_node = tmp_node; suit_size = suit_node->mem_size; } } tmp_node = tmp_node->nxt_ptr; if(tmp_node == head_node) { if(suit_node == NULL) { alloc_printf("NULL\r\n"); return NULL; } break; } } if(nbytes <= suit_node->mem_size && (nbytes + BLK_SIZE) >= suit_node->mem_size) { suit_node->mem_sta = USED; return suit_node->mem_ptr; } else if(suit_node->mem_size > (nbytes + BLK_SIZE)) { tmp_node = suit_node->mem_ptr; tmp_node = (mem_block *)((unsigned char *)tmp_node + nbytes); tmp_node->mem_ptr = suit_node->mem_ptr; tmp_node->nxt_ptr = suit_node->nxt_ptr; tmp_node->mem_size = nbytes; tmp_node->mem_sta = USED; suit_node->mem_ptr = (mem_block *)((unsigned char *)tmp_node + BLK_SIZE); suit_node->nxt_ptr = tmp_node; suit_node->mem_size -= (nbytes + BLK_SIZE); suit_node->mem_sta = UNUSED; return tmp_node->mem_ptr; } else { alloc_printf("%s,size err!\r\n",__FUNCTION__); } return NULL; } /* ******************************************************************************** * 内存释放函数 * * 描述 : 内存释放函数 * * 参数 : ap 要释放的内存块的指针。 * * 返回 : 无 ******************************************************************************** */ static void free(void *ap) { mem_block *head_node, *tmp_node, *nxt_node; if(ap == NULL) return; if(mem_init_flag < 0) { return; } head_node = tmp_node = (mem_block *)HEAD_NODE; while(1) { if(tmp_node->mem_ptr == ap) { if(tmp_node->mem_sta != UNUSED) { tmp_node->mem_sta = UNUSED; break; } else { alloc_printf("ap:0x%08x 已经释放,无需再次释放\r\n",ap); return; } } tmp_node = tmp_node->nxt_ptr; if(tmp_node == head_node) { alloc_printf("%s,can not found ap!\r\n",__FUNCTION__); return ; } } AGAIN: head_node = tmp_node = (mem_block *)HEAD_NODE; while(1) { nxt_node = tmp_node->nxt_ptr; if(nxt_node == head_node) { break; } if(tmp_node->mem_sta == UNUSED && nxt_node->mem_sta == UNUSED) { tmp_node->mem_ptr = nxt_node->mem_ptr; tmp_node->nxt_ptr = nxt_node->nxt_ptr; tmp_node->mem_size += nxt_node->mem_size + BLK_SIZE; tmp_node->mem_sta = UNUSED; goto AGAIN; } tmp_node = nxt_node; } } void *m_malloc(unsigned nbytes) { return malloc(nbytes); } void m_free(void *ap) { free(ap); }
alloc.h
#ifndef __MEM_ALLOC_H__ #define __MEM_ALLOC_H__ void *m_malloc(unsigned nbytes); void m_free(void *ap); #endif
test.c:
#ifndef __MEM_ALLOC_H__ #define __MEM_ALLOC_H__ void *m_malloc(unsigned nbytes); void m_free(void *ap); #endif

更多精彩