[KungFu8位 MCU] 单片机上内存管理(重定义malloc & free)de实现

[复制链接]
 楼主| merry_zsp 发表于 2019-5-28 22:12 | 显示全部楼层 |阅读模式
在单片机上经常会需要用到像标准c库中的内存分配,可是单片机并没有内存管理机制,如果直接调用库函数(malloc,free...),会导致内存碎片越用越多,很容易使系统崩溃掉,这里分享一个自己写的适用于单片机的内存分配方法,具备轻量级的内存管理能力,有效减少内存碎片,提高单片机系统工作稳定性。

   如下图,heap_start开始的地方,是我们存放用户数据的地方,在heap_end之前都是大小固定的一个个内存管理块,内存管理块用于记录每次用户申请内存的地址、大小、释放情况。在malloc时,会优先选择和用户申请空间最相当的内存块,以减少内存碎片产生。在free的内存块时,如果遇到相邻内存块均为空闲块时,便会将几块相邻的内存块合并成一块,以减少内存碎片。

 楼主| merry_zsp 发表于 2019-5-28 22:13 | 显示全部楼层
alloc.c
  1. /*
  2. ********************************************************************************
  3. *                                memory alloc
  4. *
  5. *                            (c) Copyright 2018-2020;
  6. *        All rights reserved.  Protected by international copyright laws.
  7. *
  8. *                                MEMORY ALLOC
  9. *
  10. * File    : mem_alloc.c
  11. * By      : Recahrd.Zhang
  12. * Version : V1.00
  13. *
  14. ********************************************************************************
  15. */
  16. #include <string.h>
  17. #include "mem_alloc.h"
  18. #include "debug.h"

  19. #define MEM_ALLOC        1
  20. #if defined (MEM_ALLOC)&&MEM_ALLOC
  21. #define alloc_printf         printf
  22. #else
  23. #define alloc_printf(argv, ...)
  24. #endif

  25. #define MEM_SIZE         2*1024             /*内存池的大小 2 KBytes*/

  26. static    char mem[MEM_SIZE];                   /*定义用来内存分配的数组*/

  27. #define MEM_START     &mem[0]                /*定义内存池的首地址*/
  28. #define MEM_END       &mem[MEM_SIZE]        /*定义内存池的尾地址*/

  29. enum USE_STA{                            /*定义内存块的使用状态(UNUSED 未使用),(USED 已使用)*/
  30.     UNUSED = 0,
  31.     USED   = 1
  32. };

  33. #pragma pack(1)
  34. typedef struct mem_block{                /*定义内存管理块的数据结构*/
  35.     void             *mem_ptr;            /*当前内存块的内存地址*/
  36.     struct mem_block     *nxt_ptr;        /*下一个内存管理块的地址*/
  37.     unsigned int         mem_size;        /*当前内存块的大小*/
  38.     enum USE_STA        mem_sta;        /*当前内存块的状态*/
  39. }mem_block;
  40. #pragma pack()


  41. #define BLK_SIZE    sizeof(mem_block)    /*内存管理块的大小*/
  42. #define HEAD_NODE    (MEM_END - BLK_SIZE)/*头内存管理块的地址*/

  43. static signed char  mem_init_flag = -1; /*内存分配系统初始化的标志(-1 未初始化),(1 已初始化)*/

  44. /*
  45. ********************************************************************************
  46. *                                   内存分配系统初始化                    
  47. *
  48. * 描述    : 初始化内存分配系统,为malloc和free做好准备工作。
  49. *
  50. * 参数  : 无
  51. *
  52. * 返回  : 无
  53. ********************************************************************************
  54. */
  55. void mem_init(void)
  56. {
  57.     mem_block     *node;
  58.      
  59.     memset(mem,    0x00UL,    sizeof(mem));
  60.      
  61.     node = (mem_block     *)HEAD_NODE;
  62.     node->mem_ptr         =     MEM_START;
  63.     node->nxt_ptr         =     (mem_block *)HEAD_NODE;
  64.     node->mem_size        =     MEM_SIZE - BLK_SIZE;
  65.     node->mem_sta        =    UNUSED;
  66.      
  67.     mem_init_flag = 1;
  68. }

  69. /*
  70. ********************************************************************************
  71. *                                   内存申请函数                    
  72. *
  73. * 描述    : 内存申请函数
  74. *
  75. * 参数  : nbytes    要申请的内存的字节数。
  76. *
  77. * 返回  : 成功        返回申请到的内存的首地址
  78. *          失败        返回NULL
  79. ********************************************************************************
  80. */
  81. static void *malloc(unsigned nbytes)
  82. {
  83.     unsigned int    suit_size = 0xFFFFFFFFUL;
  84.     mem_block     *head_node=NULL, *tmp_node=NULL, *suit_node=NULL;

  85.     if(nbytes == 0)
  86.     {
  87.         alloc_printf("参数非法!\r\n");
  88.         return NULL;
  89.     }
  90.     if(mem_init_flag < 0)
  91.     {
  92.         alloc_printf("未初始化,先初始化.\r\n");
  93.         mem_init();
  94.     }
  95.      
  96.     head_node = tmp_node = (mem_block *)HEAD_NODE;
  97.     while(1)
  98.     {
  99.         if(tmp_node->mem_sta == UNUSED)
  100.         {
  101.             if(nbytes <= tmp_node->mem_size && tmp_node->mem_size < suit_size)
  102.             {
  103.                 suit_node = tmp_node;
  104.                 suit_size = suit_node->mem_size;
  105.             }
  106.         }
  107.         tmp_node = tmp_node->nxt_ptr;
  108.         if(tmp_node == head_node)
  109.         {
  110.             if(suit_node == NULL)
  111.             {
  112.                 alloc_printf("NULL\r\n");
  113.                 return NULL;
  114.             }
  115.             break;
  116.         }
  117.     }

  118.     if(nbytes <= suit_node->mem_size && (nbytes + BLK_SIZE) >= suit_node->mem_size)
  119.     {
  120.         suit_node->mem_sta = USED;
  121.         return suit_node->mem_ptr;
  122.     }
  123.     else    if(suit_node->mem_size > (nbytes + BLK_SIZE))
  124.     {
  125.         tmp_node = suit_node->mem_ptr;
  126.         tmp_node = (mem_block *)((unsigned char *)tmp_node + nbytes);
  127.         tmp_node->mem_ptr  = suit_node->mem_ptr;
  128.         tmp_node->nxt_ptr  = suit_node->nxt_ptr;
  129.         tmp_node->mem_size = nbytes;
  130.         tmp_node->mem_sta  = USED;
  131.          
  132.         suit_node->mem_ptr      = (mem_block *)((unsigned char *)tmp_node + BLK_SIZE);
  133.         suit_node->nxt_ptr   =  tmp_node;
  134.         suit_node->mem_size -= (nbytes + BLK_SIZE);
  135.         suit_node->mem_sta   = UNUSED;
  136.          
  137.         return tmp_node->mem_ptr;
  138.     }
  139.     else
  140.     {
  141.         alloc_printf("%s,size err!\r\n",__FUNCTION__);
  142.     }
  143.      
  144.     return NULL;
  145. }

  146. /*
  147. ********************************************************************************
  148. *                                   内存释放函数                    
  149. *
  150. * 描述    : 内存释放函数
  151. *
  152. * 参数  : ap        要释放的内存块的指针。
  153. *
  154. * 返回  : 无
  155. ********************************************************************************
  156. */
  157. static void free(void *ap)
  158. {
  159.     mem_block     *head_node, *tmp_node, *nxt_node;
  160.      
  161.     if(ap == NULL)
  162.         return;
  163.     if(mem_init_flag < 0)
  164.     {
  165.         return;
  166.     }
  167.     head_node = tmp_node = (mem_block *)HEAD_NODE;
  168.     while(1)
  169.     {
  170.         if(tmp_node->mem_ptr == ap)
  171.         {
  172.             if(tmp_node->mem_sta != UNUSED)
  173.             {
  174.                 tmp_node->mem_sta = UNUSED;
  175.                 break;
  176.             }
  177.             else
  178.             {
  179.                 alloc_printf("ap:0x%08x 已经释放,无需再次释放\r\n",ap);
  180.                 return;
  181.             }
  182.         }
  183.          
  184.         tmp_node = tmp_node->nxt_ptr;
  185.         if(tmp_node == head_node)
  186.         {
  187.             alloc_printf("%s,can not found ap!\r\n",__FUNCTION__);
  188.             return ;
  189.         }
  190.     }

  191. AGAIN:   
  192.     head_node = tmp_node = (mem_block *)HEAD_NODE;
  193.     while(1)
  194.     {
  195.         nxt_node = tmp_node->nxt_ptr;
  196.         if(nxt_node == head_node)
  197.         {
  198.             break;
  199.         }
  200.         if(tmp_node->mem_sta == UNUSED && nxt_node->mem_sta == UNUSED)
  201.         {
  202.             tmp_node->mem_ptr     = nxt_node->mem_ptr;
  203.             tmp_node->nxt_ptr     = nxt_node->nxt_ptr;
  204.             tmp_node->mem_size += nxt_node->mem_size + BLK_SIZE;
  205.             tmp_node->mem_sta    =  UNUSED;
  206.             
  207.             goto AGAIN;
  208.         }
  209.         tmp_node = nxt_node;
  210.     }
  211. }

  212. void *m_malloc(unsigned nbytes)
  213. {
  214.     return malloc(nbytes);
  215. }

  216. void m_free(void *ap)
  217. {
  218.     free(ap);
  219. }
 楼主| merry_zsp 发表于 2019-5-28 22:13 | 显示全部楼层
alloc.h
  1. #ifndef __MEM_ALLOC_H__
  2. #define __MEM_ALLOC_H__

  3. void *m_malloc(unsigned nbytes);
  4. void  m_free(void *ap);

  5. #endif
 楼主| merry_zsp 发表于 2019-5-28 22:14 | 显示全部楼层
test.c:
  1. #ifndef __MEM_ALLOC_H__
  2. #define __MEM_ALLOC_H__

  3. void *m_malloc(unsigned nbytes);
  4. void  m_free(void *ap);

  5. #endif
您需要登录后才可以回帖 登录 | 注册

本版积分规则

75

主题

695

帖子

2

粉丝
快速回复 返回顶部 返回列表