单片机上内存管理(重定义malloc & free)de实现

2019-04-15 17:36发布

   在单片机上经常会需要用到像标准c库中的内存分配,可是单片机并没有内存管理机制,如果直接调用库函数(malloc,free...),会导致内存碎片越用越多,很容易使系统崩溃掉,这里分享一个自己写的适用于单片机的内存分配方法,具备轻量级的内存管理能力,有效减少内存碎片,提高单片机系统工作稳定性。    如下图,heap_start开始的地方,是我们存放用户数据的地方,在heap_end之前都是大小固定的一个个内存管理块,内存管理块用于记录每次用户申请内存的地址、大小、释放情况。在malloc时,会优先选择和用户申请空间最相当的内存块,以减少内存碎片产生。在free的内存块时,如果遇到相邻内存块均为空闲块时,便会将几块相邻的内存块合并成一块,以减少内存碎片。 源码下载: 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 #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("参数非法! ");         return NULL;     }     if(mem_init_flag < 0)     {         alloc_printf("未初始化,先初始化. ");         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 ");                 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! ",__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 已经释放,无需再次释放 ",ap);                 return;             }         }                  tmp_node = tmp_node->nxt_ptr;         if(tmp_node == head_node)         {             alloc_printf("%s,can not found ap! ",__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: #include #include "alloc.h" #define alloc_printf pritnf /* ******************************************************************************** *                                   内存打印函数                      * * 描述    : 打印内存系统中每一个内存块的信息 * * 参数  : 无 * * 返回  : 无 ******************************************************************************** */ void mem_print(void) {     unsigned int i = 0;     mem_block     *head_node, *tmp_node;     if(mem_init_flag < 0)     {         alloc_printf("未初始化,先初始化. ");         mem_init();     }     head_node = tmp_node = (mem_block *)HEAD_NODE;     alloc_printf(" ############################# ");     while(1)     {         alloc_printf(" NO.%d: ",i++);         alloc_printf("blk_ptr:0x%08x ",tmp_node);         alloc_printf("mem_ptr:0x%08x ",tmp_node->mem_ptr);         alloc_printf("nxt_ptr:0x%08x ",tmp_node->nxt_ptr);         alloc_printf("mem_size:%d ",tmp_node->mem_size);         alloc_printf("mem_sta:%d ",tmp_node->mem_sta);         tmp_node = tmp_node->nxt_ptr;         if(tmp_node == head_node)         {             break;         }     }     alloc_printf(" ############################# "); } void buff_print(unsigned char *buf,unsigned int len) {     unsigned int i;     alloc_printf(" ");     for(i=0;i