请选择 进入手机版 | 继续访问电脑版

硬汉嵌入式论坛

 找回密码
 立即注册
查看: 2197|回复: 4
收起左侧

论坛首发,内存管理算法,支持malloc,realloc,align_alloc,配有内存碎片合并算法

[复制链接]

12

主题

153

回帖

204

积分

高级会员

积分
204
发表于 2021-8-15 16:47:30 | 显示全部楼层 |阅读模式
        今天查看RTX5的内存分配源码,发现其内部实现中并没有内存碎片合并的算法,这样在随机大小分配内存时就会产生内存碎片的问题,不是很完美。而FreeRTOS的Heap4及Heap5的内存算法带有内存碎片的合并算法,但是其可移植性不好,没有对realloc、align_alloc的支持,不是很完美。
        基于这个原因,仿照了FreeRTOS中合并内存碎片的算法,自己编写了一套内存控制算法,编写完成后使用vs2015编写了相应的测试代码,测试结果较为理想。
        下面是算法源码及测试工程
        源码
        mem_manage.h
  1. /********************************************************************************
  2. * @File name: mem_manage.h
  3. * @Author: wzh
  4. * @Version: 1.1
  5. * @Date: 2021-8-14
  6. * @Description: 内存管理算法,带有内存碎片合并算法,支持malloc、align_alloc、
  7. *                                realloc、free等常见的内存管理函数,支持多块内存合并管理,支持多线程
  8. * @Todo        具体使用方法如下
  9. *                 1、使用Mem_Manage_Heap_Init(Mem_Root* pRoot, const Mem_Region* pRigon)初始化
  10. *                        内存区,pRoot为句柄,pRigon描述了内存区个数以及内个内存区起始地址和大小
  11. *                        pRigon的格式如下
  12. *                        const Mem_Region pRigon[]=
  13. *                        {
  14. *                                (void*)(0x20000000),512*1024,
  15. *                                (void*)(0x80000000),256*1024,
  16. *                                ....
  17. *                                NULL,0
  18. *                        }
  19. *                        注意地址必需由低到高排列,同时使用NULL,0标识结尾,内存区容量不要太小,至少大于64个字节
  20. *                        推荐内存区地址与内存区大小8字节对齐,这样会减少对齐操作对内存的损耗
  21. *                 2、使用Mem_Manage_Malloc、Mem_Manage_Realloc、Mem_Manage_Align_Alloc进行内存
  22. *                        分配,其中Mem_Manage_Malloc、Mem_Manage_Realloc默认均为8字节对齐,可修改
  23. *                        .c文件中的宏定义修改,Mem_Manage_Align_Alloc可以指定地址对齐,但对齐的参数
  24. *                        有限制,align_size需要为2的整数次幂,否则会直接返回NULL。
  25. *                 3、内存使用完毕后使用Mem_Manage_Free进行内存释放
  26. *                 4、可通过Mem_Manage_Get_State查看内存使用情况,通过句柄Mem_Root成员total_size获取总内存量,
  27. *                        通过Mem_State成员remain_size获取内存剩余量
  28. *                 5、使用默认的8字节对齐有助于减少小内存块,进而提高内存利用率
  29. *                 6、目前最小内存块控制为16字节,可通过.c文件进行修改
  30. *                 7、算法中使用了块大小标识的最高位作为分配标记,可在一定程度上检验非法释放,
  31. *                        但这也使得内存管理的最大内存限制为2GB(32位机)
  32. ********************************************************************************/
  33. #ifndef MEM_MANAGE_H_
  34. #define MEM_MANAGE_H_

  35. #include <stddef.h>

  36. //#define MEM_MANAGE_LOCK()
  37. //#define MEM_MANAGE_UNLOCK()
  38. #define MEM_MANAGE_ASSERT(A)                                        if(!(A))printf("MEM_MANAGE Malloc Error:%s,%d\r\n",__FILE__,__LINE__)
  39. #define MEM_MANAGE_MALLOC_FAIL()                                printf("MEM_MANAGE Malloc Fail:%s,%d\r\n",__FILE__,__LINE__)

  40. #ifndef MEM_MANAGE_LOCK
  41. #define MEM_MANAGE_LOCK()
  42. #endif

  43. #ifndef MEM_MANAGE_UNLOCK
  44. #define MEM_MANAGE_UNLOCK()
  45. #endif

  46. #ifndef MEM_MANAGE_ASSERT
  47. #define MEM_MANAGE_ASSERT(A)                        ((void)(A))
  48. #endif

  49. #ifndef MEM_MANAGE_MALLOC_FAIL
  50. #define MEM_MANAGE_MALLOC_FAIL()               
  51. #endif

  52. #ifdef __cplusplus
  53. extern "C" {
  54. #endif

  55. typedef struct Mem_Region {
  56.         void*        addr;//内存区起始地址
  57.         size_t        mem_size;//内存大小
  58. }Mem_Region;

  59. typedef struct Mem_Node {
  60.         struct Mem_Node* next_node;
  61.         size_t mem_size;
  62. }Mem_Node;

  63. typedef struct Mem_Root {
  64.         Mem_Node* pStart;
  65.         Mem_Node* pEnd;
  66.         size_t total_size;                //总内存
  67. }Mem_Root;

  68. typedef struct Mem_State {
  69.         size_t remain_size;                //内存剩余量
  70.         size_t free_node_num;        //空闲节点个数
  71.         size_t max_node_size;        //最大节点内存
  72.         size_t min_node_size;        //最小节点内存
  73. }Mem_State;

  74. void* Mem_Manage_Align_Alloc(Mem_Root* pRoot, size_t align_size, size_t want_size);
  75. void* Mem_Manage_Malloc(Mem_Root* pRoot, size_t want_size);
  76. void* Mem_Manage_Realloc(Mem_Root* pRoot, void* src_addr, size_t want_size);
  77. void Mem_Manage_Free(Mem_Root* pRoot, void* addr);
  78. void Mem_Manage_Heap_Init(Mem_Root* pRoot, const Mem_Region* pRigon);
  79. void Mem_Manage_Get_State(Mem_Root* pRoot, Mem_State* pState);
  80. #ifdef __cplusplus
  81. }
  82. #endif

  83. #endif
复制代码
      mem_manage.c
  1. /********************************************************************************
  2. * @File name: mem_manage.c
  3. * @Author: wzh
  4. * @Version: 1.1
  5. * @Date: 2021-8-14
  6. * @Description: 内存管理算法,带有内存碎片合并算法,支持malloc、align_alloc、
  7. *                                realloc、free等常见的内存管理函数,支持多块内存合并管理,支持多线程
  8. ********************************************************************************/
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include "mem_manage.h"

  13. #define MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT                8
  14. #define MEM_MANAGE_BITS_PER_BYTE                                8
  15. #define MEM_MANAGE_MEM_STRUCT_SIZE                                Mem_Manage_Align_Up(sizeof(Mem_Node),MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
  16. #define MEM_MANAGE_MINUM_MEM_SIZE                                (MEM_MANAGE_MEM_STRUCT_SIZE<<1)
  17. #define MEM_MANAGE_ALLOCA_LABAL                                        ((size_t)(1<<(sizeof(size_t)*MEM_MANAGE_BITS_PER_BYTE-1)))


  18. static inline size_t Mem_Manage_Align_Down(size_t data, size_t align_byte) {
  19.         return data&~(align_byte - 1);
  20. }

  21. static inline size_t Mem_Manage_Align_Up(size_t data, size_t align_byte) {
  22.         return (data + align_byte - 1)&~(align_byte - 1);
  23. }

  24. static inline Mem_Node* Mem_Manage_Addr_To_Mem(const void* addr) {
  25.         return (Mem_Node*)((const uint8_t*)addr - MEM_MANAGE_MEM_STRUCT_SIZE);
  26. }

  27. static inline void* Mem_Manage_Mem_To_Addr(const Mem_Node* mem_node) {
  28.         return (void*)((const uint8_t*)mem_node + MEM_MANAGE_MEM_STRUCT_SIZE);
  29. }

  30. //将内存节点插入空闲列表中
  31. static inline void Mem_Insert_Node_To_FreeList(Mem_Root* pRoot, Mem_Node* pNode) {
  32.         Mem_Node* pPriv_Node;
  33.         Mem_Node* pNext_Node;
  34.         //寻找地址与pNode相近的节点
  35.         for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pNode; pPriv_Node = pPriv_Node->next_node);
  36.         pNext_Node = pPriv_Node->next_node;
  37.         //尝试pNode与前一个块进行合并
  38.         if ((uint8_t*)Mem_Manage_Mem_To_Addr(pPriv_Node) + pPriv_Node->mem_size == (uint8_t*)pNode) {
  39.                 if (pPriv_Node != pRoot->pStart) {//不是Start块的话可以合并
  40.                         pPriv_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNode->mem_size;
  41.                         pNode = pPriv_Node;
  42.                 }
  43.                 else {//后面如果是Start块不进行合并,以免浪费内存
  44.                         pRoot->pStart->next_node = pNode;
  45.                 }
  46.         }
  47.         else {//不能合并时直接插入到空闲单链表中
  48.                 pPriv_Node->next_node = pNode;
  49.         }
  50.         //尝试后面一个块与pNode进行合并
  51.         if ((uint8_t*)Mem_Manage_Mem_To_Addr(pNode) + pNode->mem_size == (uint8_t*)pNext_Node) {
  52.                 if (pNext_Node != pRoot->pEnd) {//不是end块的话可以进行块合并
  53.                         pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
  54.                         pNode->next_node = pNext_Node->next_node;
  55.                 }
  56.                 else {//后面如果是end块不进行合并,以免浪费内存
  57.                         pNode->next_node = pRoot->pEnd;
  58.                 }
  59.         }
  60.         else {//不能合并时直接插入到空闲单链表中
  61.                 pNode->next_node = pNext_Node;
  62.         }
  63. }

  64. //获取管理内存的状态
  65. void Mem_Manage_Get_State(Mem_Root* pRoot,Mem_State* pState) {
  66.         MEM_MANAGE_ASSERT(pRoot->pStart != NULL);
  67.         MEM_MANAGE_ASSERT(pRoot->pEnd != NULL);
  68.         pState->max_node_size = pRoot->pStart->next_node->mem_size;
  69.         pState->min_node_size = pRoot->pStart->next_node->mem_size;
  70.         pState->remain_size = 0;
  71.         pState->free_node_num = 0;
  72.         MEM_MANAGE_LOCK();
  73.         for (Mem_Node* pNode = pRoot->pStart->next_node; pNode->next_node != NULL; pNode = pNode->next_node) {
  74.                 pState->remain_size += pNode->mem_size;
  75.                 pState->free_node_num ++;
  76.                 if (pNode->mem_size > pState->max_node_size)
  77.                         pState->max_node_size = pNode->mem_size;
  78.                 if (pNode->mem_size < pState->min_node_size)
  79.                         pState->min_node_size = pNode->mem_size;
  80.         }
  81.         MEM_MANAGE_UNLOCK();
  82. }

  83. //对齐分配内存
  84. void* Mem_Manage_Align_Alloc(Mem_Root* pRoot,size_t align_size, size_t want_size) {
  85.         void* pReturn = NULL;
  86.         Mem_Node* pPriv_Node,*pNow_Node;

  87.         MEM_MANAGE_ASSERT(pRoot->pStart != NULL);
  88.         MEM_MANAGE_ASSERT(pRoot->pEnd != NULL);
  89.         
  90.         
  91.         if (want_size == 0) {
  92.                 return NULL;
  93.         }

  94.         if ((want_size&MEM_MANAGE_ALLOCA_LABAL) != 0) {//内存过大
  95.                 MEM_MANAGE_MALLOC_FAIL();
  96.                 return NULL;
  97.         }

  98.         if (align_size&(align_size - 1)) {//内存对齐输入非法值
  99.                 MEM_MANAGE_MALLOC_FAIL();
  100.                 return NULL;
  101.         }
  102.         
  103.         MEM_MANAGE_LOCK();
  104.         if (want_size < MEM_MANAGE_MINUM_MEM_SIZE)
  105.                 want_size = MEM_MANAGE_MINUM_MEM_SIZE;
  106.         if (align_size < MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
  107.                 align_size = MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT;
  108.         //确保分配的单元都是MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT的整数倍
  109.         want_size = Mem_Manage_Align_Up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);

  110.         pPriv_Node = pRoot->pStart;
  111.         pNow_Node = pRoot->pStart->next_node;
  112.         
  113.         while (pNow_Node->next_node != NULL) {
  114.                 if (pNow_Node->mem_size >= want_size+ MEM_MANAGE_MEM_STRUCT_SIZE) {
  115.                         size_t use_align_size;
  116.                         size_t new_size;
  117.                         pReturn = (void*)Mem_Manage_Align_Up((size_t)Mem_Manage_Mem_To_Addr(pNow_Node), align_size);//计算出对齐的地址
  118.                         use_align_size = (uint8_t*)pReturn-(uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node);//计算对齐所消耗的内存
  119.                         if (use_align_size != 0) {//内存不对齐
  120.                                 if (use_align_size < MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE) {//不对齐的值过小
  121.                                         pReturn = (void*)Mem_Manage_Align_Up(\
  122.                                                 (size_t)Mem_Manage_Mem_To_Addr(pNow_Node)+ MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE, align_size);
  123.                                         use_align_size = (uint8_t*)pReturn - (uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node);
  124.                                 }
  125.                                 if (use_align_size <= pNow_Node->mem_size) {
  126.                                         new_size = pNow_Node->mem_size - use_align_size;//计算去除对齐消耗的内存剩下的内存大小
  127.                                         if (new_size >= want_size) {//满足条件,可以进行分配
  128.                                                 Mem_Node* pNew_Node = Mem_Manage_Addr_To_Mem(pReturn);
  129.                                                 pNow_Node->mem_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE;//分裂节点
  130.                                                 pNew_Node->mem_size = new_size;//新节点本来也不在空闲链表中,不用从空闲链表中排出
  131.                                                 pNew_Node->next_node = NULL;
  132.                                                 pNow_Node = pNew_Node;
  133.                                                 break;
  134.                                         }
  135.                                 }
  136.                         }
  137.                         else {//内存直接就是对齐的
  138.                                 pPriv_Node->next_node = pNow_Node->next_node;//排出空闲链表
  139.                                 pNow_Node->next_node = NULL;
  140.                                 break;
  141.                         }
  142.                 }
  143.                 pPriv_Node = pNow_Node;
  144.                 pNow_Node = pNow_Node->next_node;
  145.         }

  146.         if (pNow_Node == pRoot->pEnd){//分配失败
  147.                 MEM_MANAGE_UNLOCK();
  148.                 MEM_MANAGE_MALLOC_FAIL();
  149.                 return NULL;
  150.         }

  151.         if (pNow_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE + want_size) {//节点内存还有富余
  152.                 Mem_Node* pNew_Node =(Mem_Node*)((uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node) + want_size);//计算将要移入空闲链表的节点地址
  153.                 pNew_Node->mem_size = pNow_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
  154.                 pNew_Node->next_node = NULL;
  155.                 pNow_Node->mem_size = want_size;
  156.                 Mem_Insert_Node_To_FreeList(pRoot, pNew_Node);
  157.         }
  158.         pNow_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//标记内存已分配
  159.         MEM_MANAGE_UNLOCK();
  160.         return pReturn;
  161. }

  162. void* Mem_Manage_Malloc(Mem_Root* pRoot, size_t want_size) {
  163.         return Mem_Manage_Align_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  164. }

  165. void* Mem_Manage_Realloc(Mem_Root* pRoot, void* src_addr, size_t want_size) {
  166.         void* pReturn = NULL;
  167.         Mem_Node* pNext_Node,*pPriv_Node;
  168.         Mem_Node* pSrc_Node;
  169.         MEM_MANAGE_ASSERT(pRoot->pStart != NULL);
  170.         MEM_MANAGE_ASSERT(pRoot->pEnd != NULL);
  171.         if (src_addr == NULL) {
  172.                 return Mem_Manage_Align_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  173.         }
  174.         if (want_size == 0) {
  175.                 Mem_Manage_Free(pRoot, src_addr);
  176.                 return NULL;
  177.         }

  178.         MEM_MANAGE_LOCK();
  179.         if ((want_size&MEM_MANAGE_ALLOCA_LABAL) != 0){
  180.                 MEM_MANAGE_UNLOCK();
  181.                 MEM_MANAGE_MALLOC_FAIL();
  182.                 return NULL;
  183.         }

  184.         pSrc_Node = Mem_Manage_Addr_To_Mem(src_addr);

  185.         if ((pSrc_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) == 0) {//源地址未被分配,调用错误
  186.                 MEM_MANAGE_UNLOCK();
  187.                 MEM_MANAGE_ASSERT((pSrc_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) != 0);
  188.                 MEM_MANAGE_MALLOC_FAIL();
  189.                 return NULL;
  190.         }

  191.         pSrc_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;//清除分配标记
  192.         if (pSrc_Node->mem_size >= want_size) {//块预留地址足够大
  193.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  194.                 pReturn = src_addr;
  195.                 MEM_MANAGE_UNLOCK();
  196.                 return pReturn;
  197.         }
  198.         //开始在空闲列表中寻找与本块相近的块
  199.         for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node <pSrc_Node; pPriv_Node = pPriv_Node->next_node);
  200.         pNext_Node = pPriv_Node->next_node;

  201.         if (pNext_Node != pRoot->pEnd && \
  202.                 ((uint8_t*)src_addr + pSrc_Node->mem_size == (uint8_t*)pNext_Node) && \
  203.                 (pSrc_Node->mem_size + pNext_Node->mem_size + MEM_MANAGE_MEM_STRUCT_SIZE >= want_size)) {
  204.                 //满足下一节点非end,内存连续,内存剩余足够
  205.                 pReturn = src_addr;
  206.                 pPriv_Node->next_node = pNext_Node->next_node;//排出空闲列表
  207.                 pSrc_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
  208.                 want_size = Mem_Manage_Align_Up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  209.                 if (pSrc_Node->mem_size >= MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE+ want_size) {//去除分配的剩余空间足够开辟新块
  210.                         Mem_Node* pNew_Node = (Mem_Node*)((uint8_t*)Mem_Manage_Mem_To_Addr(pSrc_Node) + want_size);
  211.                         pNew_Node->next_node = NULL;
  212.                         pNew_Node->mem_size = pSrc_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
  213.                         pSrc_Node->mem_size = want_size;
  214.                         Mem_Insert_Node_To_FreeList(pRoot, pNew_Node);
  215.                 }
  216.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  217.                 MEM_MANAGE_UNLOCK();
  218.         }
  219.         else {
  220.                 MEM_MANAGE_UNLOCK();
  221.                 pReturn = Mem_Manage_Align_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  222.                 if (pReturn == NULL){
  223.                         pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  224.                         MEM_MANAGE_MALLOC_FAIL();
  225.                         return NULL;
  226.                 }
  227.                 MEM_MANAGE_LOCK();
  228.                 memcpy(pReturn, src_addr, pSrc_Node->mem_size);
  229.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  230.                 MEM_MANAGE_UNLOCK();
  231.                 Mem_Manage_Free(pRoot, src_addr);
  232.         }
  233.         return pReturn;
  234. }

  235. //释放内存
  236. void Mem_Manage_Free(Mem_Root* pRoot,void* addr) {
  237.         Mem_Node* pFree_Node;
  238.         MEM_MANAGE_ASSERT(pRoot->pStart != NULL);
  239.         MEM_MANAGE_ASSERT(pRoot->pEnd != NULL);
  240.         MEM_MANAGE_LOCK();
  241.         if (addr == NULL) {
  242.                 MEM_MANAGE_UNLOCK();
  243.                 return;
  244.         }
  245.         pFree_Node = Mem_Manage_Addr_To_Mem(addr);

  246.         if ((pFree_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) == 0) {//释放错误,没有标记
  247.                 MEM_MANAGE_UNLOCK();
  248.                 MEM_MANAGE_ASSERT((pFree_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) != 0);
  249.                 return;
  250.         }

  251.         if (pFree_Node->next_node != NULL) {//释放错误
  252.                 MEM_MANAGE_UNLOCK();
  253.                 MEM_MANAGE_ASSERT(pFree_Node->next_node == NULL);
  254.                 return;
  255.         }
  256.         pFree_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;//清除分配标记
  257.         Mem_Insert_Node_To_FreeList(pRoot, pFree_Node);//插入到空闲链表中
  258.         MEM_MANAGE_UNLOCK();
  259. }

  260. void Mem_Manage_Heap_Init(Mem_Root* pRoot,const Mem_Region* pRegion) {
  261.         Mem_Node* align_addr;
  262.         size_t align_size;
  263.         Mem_Node* pPriv_node=NULL;

  264.         pRoot->total_size = 0;
  265.         pRoot->pEnd = NULL;
  266.         pRoot->pStart = NULL;

  267.         for (; pRegion->addr != NULL; pRegion++) {
  268.                 align_addr = (Mem_Node*)Mem_Manage_Align_Up((size_t)pRegion->addr, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);//计算内存块对齐后的地址
  269.                 if ((uint8_t*)align_addr > pRegion->mem_size+ (uint8_t*)pRegion->addr)//对齐消耗的内存超过内存区
  270.                         continue;
  271.                 align_size = pRegion->mem_size - ((uint8_t*)align_addr - (uint8_t*)pRegion->addr);//计算对齐后剩下的内存大小
  272.                 if (align_size < MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE)//对齐剩下的内存太小
  273.                         continue;
  274.                 align_size -= MEM_MANAGE_MEM_STRUCT_SIZE;//求除去掉表头后内存块的大小
  275.                 align_addr->mem_size = align_size;
  276.                 align_addr->next_node = NULL;
  277.                 if (pRoot->pStart == NULL) {//如果是初始化
  278.                         pRoot->pStart = align_addr;//将当前内存块地址记为start
  279.                         if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE) {//若剩下的块足够大
  280.                                 align_size -= MEM_MANAGE_MEM_STRUCT_SIZE;//去掉下一个块的表头剩下的内存大小
  281.                                 align_addr = (Mem_Node*)((uint8_t*)pRoot->pStart + MEM_MANAGE_MEM_STRUCT_SIZE);//下一个块的表头地址
  282.                                 align_addr->mem_size = align_size;
  283.                                 align_addr->next_node = NULL;
  284.                                 pRoot->pStart->mem_size = 0;
  285.                                 pRoot->pStart->next_node = align_addr;
  286.                                 pRoot->total_size = align_addr->mem_size;
  287.                         }
  288.                         else {//内存太小了,将当前内存块地址记为start
  289.                                 pRoot->total_size = 0;
  290.                                 pRoot->pStart->mem_size = 0;
  291.                         }
  292.                 }
  293.                 else {
  294.                         pPriv_node->next_node = align_addr;//更新上一节点的next_node
  295.                         pRoot->total_size += align_size;
  296.                 }
  297.                 pPriv_node = align_addr;
  298.         }
  299.         //此时,pPriv_node为最后一个块,接下来在块尾放置表尾end
  300.         //求出放置end块的地址,end块仅是方便遍历使用,因此尽量小,分配为MEM_MANAGE_MEM_STRUCT_SIZE
  301.         align_addr = (Mem_Node*)Mem_Manage_Align_Down(\
  302.                 (size_t)Mem_Manage_Mem_To_Addr(pPriv_node) + pPriv_node->mem_size - MEM_MANAGE_MEM_STRUCT_SIZE, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  303.         align_size = (uint8_t*)align_addr-(uint8_t*)Mem_Manage_Mem_To_Addr(pPriv_node);//求出分配出end块后,前一个块剩余大小
  304.         if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE) {//若剩下的块足够大
  305.                 pRoot->total_size -= pPriv_node->mem_size - align_size;//去掉分配end块消耗的内存
  306.                 pRoot->pEnd = align_addr;                        //更新表尾的地址
  307.                 pPriv_node->next_node = align_addr;
  308.                 pPriv_node->mem_size = align_size;
  309.                 align_addr->next_node = NULL;
  310.                 align_addr->mem_size = 0;//end块不参与内存分配,因此直接为0就可以
  311.         }
  312.         else {//最后一个块太小了,直接作为end块
  313.                 pRoot->pEnd = pPriv_node;
  314.                 pRoot->total_size -= pPriv_node->mem_size;
  315.         }
  316.         MEM_MANAGE_ASSERT(pRoot->pStart != NULL);
  317.         MEM_MANAGE_ASSERT(pRoot->pEnd != NULL);
  318. }


复制代码




        测试工程已上传到附件中。
        算法管理内存的方式是通过单链表的形式进行管理,每个空闲块按地址顺序进行排列,算法内部通过宏定义MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT控制对齐,所有的内存元素都会以这个参数进行内存对齐,代表了算法中数据的最小单元,因此以该值作为对齐分配的参数,算法效率最高。
        算法中初始化内存管理区的函数为void Mem_Manage_Heap_Init(Mem_Root* pRoot,const Mem_Region* pRegion) ,支持管理不连续的内存,适合像STM32H7这样内存单元不连续的情况,具体使用说明可以看头文件的说明。
        算法支持malloc、realloc、align_alloc等常见的内存管理函数,在使用align_alloc时注意其中align_size输入,此参数指定了分配内存的对齐字节,如输入为1024,则算法保证分配的地址是1024字节对齐的,注意此参数输入只能为2的整数次幂,也就是诸如4、8、16、32这样的数值,输入值非法会直接返回NULL。
        算法支持多线程,通过重定义头文件的MEM_MANAGE_LOCK()与MEM_MANAGE_UNLOCK()即可实现。
        算法采用句柄的方式管理内存区,内部无全局变量,因此可支持多个内存区分别管理,只需要使用不同的句柄即可。
        在仿真工程中有过对算法效率的统计,当malloc或realloc返回值出现NULL时计算内存使用率,平均下来内存使用率大致在99%左右。
        仿真工程是使用vs2015进行测试,内部共有三个文件,其中mem_manage.c、mem_manage.h为算法源码,main.c为测试程序。
        程序开源,大家放心使用,也欢迎大家来帖子下面讨论算法中不完善的地方。
       

Mem_manage_test.zip

3.48 MB, 下载次数: 466

算法测试工程

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106398
QQ
发表于 2021-8-16 14:06:04 | 显示全部楼层
谢谢楼主分享。
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-8-23 20:41:18 | 显示全部楼层

回复

使用道具 举报

3

主题

1220

回帖

1229

积分

至尊会员

积分
1229
发表于 2021-12-5 14:13:06 | 显示全部楼层
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-12-5 19:16:03 | 显示全部楼层
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-19 05:36 , Processed in 0.298866 second(s), 31 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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