硬汉嵌入式论坛

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

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

  [复制链接]

12

主题

153

回帖

204

积分

高级会员

积分
204
发表于 2021-9-3 11:12:56 | 显示全部楼层 |阅读模式
本帖最后由 WZH 于 2021-9-3 11:15 编辑

前文:论坛首发,内存管理算法,支持malloc,realloc,align_alloc,配有内存碎片合并算法http://armbbs.cn/forum.php?mod=v ... 08321&fromuid=24016
(出处: 硬汉嵌入式论坛)
本次算法进行了部分更新,主要添加内存池式的初始化与分配方法,与硬汉哥在H7教程中的内存管理方法使用方式完全一致,另外代码是根据C99标准编写的,因此编译时需要勾选C99选项。
mem_manage.h
  1. /********************************************************************************
  2. * @File name: mem_manage.h
  3. * @Author: wzh
  4. * @Version: 1.2
  5. * @Date: 2021-9-3
  6. * @Description: 内存管理算法,带有内存碎片合并算法,支持malloc、align_alloc、
  7. *                                realloc、free等常见的内存管理函数,支持多块内存合并管理
  8. *更新记录:
  9. *                v1.0 2021-8-13  添加Mem_Manage_Heap_Init、Mem_Manage_Malloc、Mem_Manage_Realloc
  10.                                                 Mem_Manage_Aligned_Alloc函数
  11.                 v1.1 2021-8-14        添加Mem_Manage_Get_State函数
  12.                 v1.2 2021-9-3        更改Mem_Root结构体成员;更改Mem_State结构体成员;
  13.                                                 添加枚举类型Mem_Err_Type;将函数Mem_Manage_Heap_Init重命名为
  14.                                                 Mem_Manage_Init;修改Mem_Manage_Init函数声明;添加函数Mem_Manage_Get_Total_Size、
  15.                                                 Mem_Manage_Get_Remain_Size、Mem_Manage_Get_Errflag、Mem_Manage_Pool_Init、
  16.                                                 Mem_Manage_Pool_Malloc、Mem_Manage_Pool_Realloc、Mem_Manage_Pool_Aligned_Alloc、
  17.                                                 Mem_Manage_Pool_Free、Mem_Manage_Pool_Get_State、Mem_Manage_Pool_Get_Total_Size、
  18.                                                 Mem_Manage_Pool_Get_Remain_Size、Mem_Manage_Pool_Get_Errflag;
  19. * @Todo        具体使用方法如下
  20. *                 1、使用Mem_Manage_Init(Mem_Root* pRoot, const Mem_Region* pRigon)初始化
  21. *                        内存区,pRoot为句柄,pRigon描述了内存区个数以及内个内存区起始地址和大小
  22. *                        pRigon的格式如下
  23. *                        const Mem_Region pRigon[]=
  24. *                        {
  25. *                                (void*)(0x20000000),512*1024,
  26. *                                (void*)(0x80000000),256*1024,
  27. *                                ....
  28. *                                NULL,0
  29. *                        }
  30. *                        注意地址必需由低到高排列,同时使用NULL,0标识结尾,内存区容量不要太小,至少大于64个字节
  31. *                 2、使用Mem_Manage_Malloc、Mem_Manage_Realloc、Mem_Manage_Aligned_Alloc进行内存
  32. *                        分配,其中Mem_Manage_Malloc、Mem_Manage_Realloc默认均为8字节对齐,可修改
  33. *                        .c文件中的宏定义修改,Mem_Manage_Aligned_Alloc可以指定地址对齐,但对齐的参数
  34. *                        有限制,align_size需要为2的整数次幂,否则会直接返回NULL。
  35. *                 3、内存使用完毕后使用Mem_Manage_Free进行内存释放
  36. *                 4、可通过Mem_Manage_Get_State查看空闲内存状态,通过Mem_Manage_Get_Total_Size获取总内存,
  37. *                        通过Mem_Manage_Get_Remain_Size获取剩余内存               
  38. *                 5、算法管理的单个内存上限为2GB(32位机)
  39. ********************************************************************************/
  40. #ifndef MEM_MANAGE_H_
  41. #define MEM_MANAGE_H_

  42. #include <stddef.h>
  43. #include <stdbool.h>

  44. #ifdef __cplusplus
  45. extern "C" {
  46. #endif

  47. typedef enum {
  48.         MEM_NO_ERR=0X1234,                //无错误
  49.         MEM_NO_INIT=0,                        //内存区未初始化
  50.         MEM_OVER_WRITE=1                //内存区节点信息位置数据损坏
  51. }Mem_Err_Type;

  52. typedef struct Mem_Region {
  53.         void*        addr;//内存区起始地址
  54.         size_t        mem_size;//内存大小
  55. }Mem_Region;

  56. typedef struct Mem_Node {
  57.         struct Mem_Node* next_node;
  58.         size_t mem_size;
  59. }Mem_Node;

  60. typedef struct Mem_Root {
  61.         Mem_Node* pStart;
  62.         Mem_Node* pEnd;
  63.         size_t total_size;                //总内存
  64.         size_t remain_size;                //剩余内存
  65.         Mem_Err_Type err_flag;        //错误标记
  66. }Mem_Root;

  67. typedef struct Mem_State {
  68.         size_t free_node_num;        //空闲节点个数
  69.         size_t max_node_size;        //最大节点内存
  70.         size_t min_node_size;        //最小节点内存
  71. }Mem_State;


  72. bool Mem_Manage_Init(Mem_Root* pRoot, const Mem_Region* pRigon);
  73. void* Mem_Manage_Malloc(Mem_Root* pRoot, size_t want_size);
  74. void* Mem_Manage_Realloc(Mem_Root* pRoot, void* src_addr, size_t want_size);
  75. void* Mem_Manage_Aligned_Alloc(Mem_Root* pRoot, size_t align_size, size_t want_size);
  76. void Mem_Manage_Free(Mem_Root* pRoot, void* addr);
  77. void Mem_Manage_Get_State(Mem_Root* pRoot, Mem_State* pState);
  78. size_t Mem_Manage_Get_Total_Size(const Mem_Root* pRoot);
  79. size_t Mem_Manage_Get_Remain_Size(const Mem_Root* pRoot);
  80. Mem_Err_Type Mem_Manage_Get_Errflag(const Mem_Root* pRoot);

  81. bool Mem_Manage_Pool_Init(void* mem_addr,size_t mem_size);
  82. void* Mem_Manage_Pool_Malloc(void* mem_addr,size_t want_size);
  83. void* Mem_Manage_Pool_Realloc(void* mem_addr,void* src_addr,size_t want_size);
  84. void* Mem_Manage_Pool_Aligned_Alloc(void* mem_addr,size_t align_byte,size_t want_size);
  85. void Mem_Manage_Pool_Free(void* mem_addr,void* free_addr);
  86. void Mem_Manage_Pool_Get_State(void* mem_addr,Mem_State* pState);
  87. size_t Mem_Manage_Pool_Get_Total_Size(const void* mem_addr);
  88. size_t Mem_Manage_Pool_Get_Remain_Size(const void* mem_addr);
  89. Mem_Err_Type Mem_Manage_Pool_Get_Errflag(const void* mem_addr);

  90. #ifdef __cplusplus
  91. }
  92. #endif

  93. #endif

复制代码

mem_manage.h
  1. /********************************************************************************
  2. * @File name: mem_manage.c
  3. * @Author: wzh
  4. * @Version: 1.2
  5. * @Date: 2021-9-3
  6. * @Description: 内存管理算法,带有内存碎片合并算法,支持malloc、align_alloc、
  7. *                                realloc、free等常见的内存管理函数,支持多块内存合并管理
  8. *更新记录:
  9. *                v1.0 2021-8-13  添加Mem_Manage_Heap_Init、Mem_Manage_Malloc、Mem_Manage_Realloc
  10.                                                 Mem_Manage_Aligned_Alloc函数
  11.                 v1.1 2021-8-14        添加Mem_Manage_Get_State函数
  12.                 v1.2 2021-9-3        更改Mem_Root结构体成员;更改Mem_State结构体成员;
  13.                                                 添加枚举类型Mem_Err_Type;将函数Mem_Manage_Heap_Init重命名为
  14.                                                 Mem_Manage_Init;修改Mem_Manage_Init函数声明;添加函数Mem_Manage_Get_Total_Size、
  15.                                                 Mem_Manage_Get_Remain_Size、Mem_Manage_Get_Errflag、Mem_Manage_Pool_Init、
  16.                                                 Mem_Manage_Pool_Malloc、Mem_Manage_Pool_Realloc、Mem_Manage_Pool_Aligned_Alloc、
  17.                                                 Mem_Manage_Pool_Free、Mem_Manage_Pool_Get_State、Mem_Manage_Pool_Get_Total_Size、
  18.                                                 Mem_Manage_Pool_Get_Remain_Size、Mem_Manage_Pool_Get_Errflag;
  19. ********************************************************************************/
  20. #include <stdint.h>
  21. #include <string.h>
  22. #include "mem_manage.h"

  23. #define MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT                8
  24. #define MEM_MANAGE_BITS_PER_BYTE                                8
  25. #define MEM_MANAGE_MEM_STRUCT_SIZE                                Mem_Manage_Align_Up(sizeof(Mem_Node),MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
  26. #define MEM_MANAGE_MINUM_MEM_SIZE                                (MEM_MANAGE_MEM_STRUCT_SIZE<<1)
  27. #define MEM_MANAGE_ALLOCA_LABAL                                        ((size_t)(1<<(sizeof(size_t)*MEM_MANAGE_BITS_PER_BYTE-1)))
  28. #define MEM_MANAGE_MINUM_NODE_SIZE                                (MEM_MANAGE_MEM_STRUCT_SIZE+MEM_MANAGE_MINUM_MEM_SIZE)
  29. #define MEM_MANAGE_MEM_ROOT_SIZE                                Mem_Manage_Align_Up(sizeof(Mem_Root),MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)

  30. static __inline size_t Mem_Manage_Align_Down(size_t data, size_t align_byte) {
  31.         return data&~(align_byte - 1);
  32. }

  33. static __inline size_t Mem_Manage_Align_Up(size_t data, size_t align_byte) {
  34.         return (data + align_byte - 1)&~(align_byte - 1);
  35. }

  36. static __inline Mem_Node* Mem_Manage_Addr_To_Mem(const void* addr) {
  37.         return (Mem_Node*)((const uint8_t*)addr - MEM_MANAGE_MEM_STRUCT_SIZE);
  38. }

  39. static __inline void* Mem_Manage_Mem_To_Addr(const Mem_Node* mem_node) {
  40.         return (void*)((const uint8_t*)mem_node + MEM_MANAGE_MEM_STRUCT_SIZE);
  41. }

  42. //将内存节点插入空闲列表中
  43. static __inline void Mem_Insert_Node_To_FreeList(Mem_Root* pRoot, Mem_Node* pNode) {
  44.         Mem_Node* pPriv_Node;
  45.         Mem_Node* pNext_Node;
  46.         //寻找地址与pNode相近的节点
  47.         for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node < pNode; pPriv_Node = pPriv_Node->next_node);
  48.         pNext_Node = pPriv_Node->next_node;
  49.         pRoot->remain_size += pNode->mem_size;
  50.         //尝试pNode与前一个块进行合并
  51.         if ((uint8_t*)Mem_Manage_Mem_To_Addr(pPriv_Node) + pPriv_Node->mem_size == (uint8_t*)pNode) {
  52.                 if (pPriv_Node != pRoot->pStart) {//不是Start块的话可以合并
  53.                         pPriv_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNode->mem_size;
  54.                         pRoot->remain_size += MEM_MANAGE_MEM_STRUCT_SIZE;
  55.                         pNode = pPriv_Node;
  56.                 }
  57.                 else {//后面如果是Start块不进行合并,以免浪费内存
  58.                         pRoot->pStart->next_node = pNode;
  59.                 }
  60.         }
  61.         else {//不能合并时直接插入到空闲单链表中
  62.                 pPriv_Node->next_node = pNode;
  63.         }
  64.         //尝试后面一个块与pNode进行合并
  65.         if ((uint8_t*)Mem_Manage_Mem_To_Addr(pNode) + pNode->mem_size == (uint8_t*)pNext_Node) {
  66.                 if (pNext_Node != pRoot->pEnd) {//不是end块的话可以进行块合并
  67.                         pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
  68.                         pRoot->remain_size += MEM_MANAGE_MEM_STRUCT_SIZE;
  69.                         pNode->next_node = pNext_Node->next_node;
  70.                 }
  71.                 else {//后面如果是end块不进行合并,以免浪费内存
  72.                         pNode->next_node = pRoot->pEnd;
  73.                 }
  74.         }
  75.         else {//不能合并时直接插入到空闲单链表中
  76.                 pNode->next_node = pNext_Node;
  77.         }
  78. }

  79. static __inline void Mem_Settle(Mem_Root* pRoot){
  80.         Mem_Node* pNode=pRoot->pStart->next_node;
  81.         while(pNode->next_node!=pRoot->pEnd){
  82.                 if((uint8_t*)Mem_Manage_Mem_To_Addr(pNode)+pNode->mem_size==(uint8_t*)pNode->next_node){
  83.                         pNode->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE+pNode->next_node->mem_size;
  84.                         pRoot->remain_size += MEM_MANAGE_MEM_STRUCT_SIZE;
  85.                         pNode->next_node=pNode->next_node->next_node;
  86.                 }
  87.                 else
  88.                         pNode=pNode->next_node;
  89.         }
  90. }

  91. //获取管理内存的状态
  92. //pRoot:句柄指针
  93. //pState:状态信息结构体指针
  94. //return:无返回值
  95. void Mem_Manage_Get_State(Mem_Root* pRoot,Mem_State* pState) {
  96.         
  97.         if(pRoot->err_flag!=MEM_NO_ERR){
  98.                 pState->free_node_num=0;
  99.                 pState->max_node_size=0;
  100.                 pState->min_node_size=0;
  101.                 return;
  102.         }
  103.         
  104.         if(pRoot->pStart==NULL||pRoot->pEnd==NULL){
  105.                 pRoot->err_flag=MEM_NO_INIT;
  106.                 pState->free_node_num=0;
  107.                 pState->max_node_size=0;
  108.                 pState->min_node_size=0;
  109.                 return;
  110.         }
  111.         pState->max_node_size = pRoot->pStart->next_node->mem_size;
  112.         pState->min_node_size = pRoot->pStart->next_node->mem_size;
  113.         pState->free_node_num = 0;
  114.         for (Mem_Node* pNode = pRoot->pStart->next_node; pNode->next_node != NULL; pNode = pNode->next_node) {
  115.                 pState->free_node_num ++;
  116.                 if (pNode->mem_size > pState->max_node_size)
  117.                         pState->max_node_size = pNode->mem_size;
  118.                 if (pNode->mem_size < pState->min_node_size)
  119.                         pState->min_node_size = pNode->mem_size;
  120.         }
  121. }

  122. //与C库函数aligned_alloc作用一致
  123. //pRoot:句柄指针
  124. //align_size:期望分配的内存几字节对齐(8、16、32...)
  125. //want_size:期望分配内存大小
  126. //return:        NULL 分配失败(内存不足或者错误标记不为MEM_NO_ERR);
  127. //                        其他值 分配成功
  128. void* Mem_Manage_Aligned_Alloc(Mem_Root* pRoot,size_t align_size, size_t want_size) {
  129.         void* pReturn = NULL;
  130.         Mem_Node* pPriv_Node,*pNow_Node;

  131.         if(pRoot->err_flag!=MEM_NO_ERR){
  132.                 return NULL;
  133.         }
  134.         
  135.         if(pRoot->pStart==NULL||pRoot->pEnd==NULL){
  136.                 pRoot->err_flag=MEM_NO_INIT;
  137.                 return NULL;
  138.         }
  139.         
  140.         if (want_size == 0) {
  141.                 return NULL;
  142.         }

  143.         if ((want_size&MEM_MANAGE_ALLOCA_LABAL) != 0) {//内存过大
  144.                 return NULL;
  145.         }

  146.         if (align_size&(align_size - 1)) {//内存对齐输入非法值
  147.                 return NULL;
  148.         }
  149.         
  150.         if (want_size < MEM_MANAGE_MINUM_MEM_SIZE)
  151.                 want_size = MEM_MANAGE_MINUM_MEM_SIZE;
  152.         if (align_size < MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)
  153.                 align_size = MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT;
  154.         //确保分配的单元都是MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT的整数倍
  155.         want_size = Mem_Manage_Align_Up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);

  156.         pPriv_Node = pRoot->pStart;
  157.         pNow_Node = pRoot->pStart->next_node;
  158.         
  159.         while (pNow_Node->next_node != NULL) {
  160.                 if (pNow_Node->mem_size >= want_size+ MEM_MANAGE_MEM_STRUCT_SIZE) {
  161.                         size_t use_align_size;
  162.                         size_t new_size;
  163.                         pReturn = (void*)Mem_Manage_Align_Up((size_t)Mem_Manage_Mem_To_Addr(pNow_Node), align_size);//计算出对齐的地址
  164.                         use_align_size = (uint8_t*)pReturn-(uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node);//计算对齐所消耗的内存
  165.                         if (use_align_size != 0) {//内存不对齐
  166.                                 if (use_align_size < MEM_MANAGE_MINUM_NODE_SIZE) {//不对齐的值过小
  167.                                         pReturn = (void*)Mem_Manage_Align_Up(\
  168.                                                 (size_t)Mem_Manage_Mem_To_Addr(pNow_Node)+ MEM_MANAGE_MINUM_NODE_SIZE, align_size);
  169.                                         use_align_size = (uint8_t*)pReturn - (uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node);
  170.                                 }
  171.                                 if (use_align_size <= pNow_Node->mem_size) {
  172.                                         new_size = pNow_Node->mem_size - use_align_size;//计算去除对齐消耗的内存剩下的内存大小
  173.                                         if (new_size >= want_size) {//满足条件,可以进行分配
  174.                                                 Mem_Node* pNew_Node = Mem_Manage_Addr_To_Mem(pReturn);
  175.                                                 pNow_Node->mem_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE;//分裂节点
  176.                                                 pRoot->remain_size -= new_size + MEM_MANAGE_MEM_STRUCT_SIZE;
  177.                                                 pNew_Node->mem_size = new_size;//新节点本来也不在空闲链表中,不用从空闲链表中排出
  178.                                                 pNew_Node->next_node = (Mem_Node*)MEM_NO_ERR;
  179.                                                 pNow_Node = pNew_Node;
  180.                                                 break;
  181.                                         }
  182.                                 }
  183.                         }
  184.                         else {//内存直接就是对齐的
  185.                                 pPriv_Node->next_node = pNow_Node->next_node;//排出空闲链表
  186.                                 pNow_Node->next_node = (Mem_Node*)MEM_NO_ERR;
  187.                                 pRoot->remain_size -= pNow_Node->mem_size;
  188.                                 break;
  189.                         }
  190.                 }
  191.                 pPriv_Node = pNow_Node;
  192.                 pNow_Node = pNow_Node->next_node;
  193.         }

  194.         if (pNow_Node->next_node == NULL){//分配失败
  195.                 if(pNow_Node!=pRoot->pEnd){
  196.                         pRoot->err_flag=MEM_OVER_WRITE;
  197.                 }
  198.                 return NULL;
  199.         }
  200.         pNow_Node->next_node = NULL;
  201.         if (pNow_Node->mem_size >= MEM_MANAGE_MINUM_NODE_SIZE + want_size) {//节点内存还有富余
  202.                 Mem_Node* pNew_Node =(Mem_Node*)((uint8_t*)Mem_Manage_Mem_To_Addr(pNow_Node) + want_size);//计算将要移入空闲链表的节点地址
  203.                 pNew_Node->mem_size = pNow_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
  204.                 pNew_Node->next_node = NULL;
  205.                 pNow_Node->mem_size = want_size;
  206.                 Mem_Insert_Node_To_FreeList(pRoot, pNew_Node);
  207.         }
  208.         pNow_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//标记内存已分配
  209.         return pReturn;
  210. }

  211. //与C库函数malloc作用相同
  212. //pRoot:句柄指针
  213. //want_size:期望分配内存大小
  214. //return:        NULL 分配失败(内存不足或者错误标记不为MEM_NO_ERR);
  215. //                        其他值 分配成功
  216. void* Mem_Manage_Malloc(Mem_Root* pRoot, size_t want_size) {
  217.         return Mem_Manage_Aligned_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  218. }

  219. //与C库函数realloc作用相同
  220. //pRoot:句柄指针
  221. //src_addr:源地址指针
  222. //want_size:期望分配内存大小
  223. //return:        NULL 分配失败(内存不足或者句柄错误标记不为MEM_NO_ERR);
  224. //                        其他值 分配成功
  225. void* Mem_Manage_Realloc(Mem_Root* pRoot, void* src_addr, size_t want_size) {
  226.         void* pReturn = NULL;
  227.         Mem_Node* pNext_Node,*pPriv_Node;
  228.         Mem_Node* pSrc_Node;
  229.         
  230.         if(pRoot->err_flag!=MEM_NO_ERR){
  231.                 return NULL;
  232.         }
  233.         
  234.         if(pRoot->pStart==NULL||pRoot->pEnd==NULL){
  235.                 pRoot->err_flag=MEM_NO_INIT;
  236.                 return NULL;
  237.         }
  238.         
  239.         if (src_addr == NULL) {
  240.                 return Mem_Manage_Aligned_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  241.         }
  242.         if (want_size == 0) {
  243.                 Mem_Manage_Free(pRoot, src_addr);
  244.                 return NULL;
  245.         }

  246.         if ((want_size&MEM_MANAGE_ALLOCA_LABAL) != 0){
  247.                 return NULL;
  248.         }

  249.         pSrc_Node = Mem_Manage_Addr_To_Mem(src_addr);

  250.         if ((pSrc_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) == 0) {//源地址未被分配,调用错误
  251.                 pRoot->err_flag=MEM_OVER_WRITE;
  252.                 return NULL;
  253.         }

  254.         pSrc_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;//清除分配标记
  255.         if (pSrc_Node->mem_size >= want_size) {//块预留地址足够大
  256.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  257.                 pReturn = src_addr;
  258.                 return pReturn;
  259.         }
  260.         //开始在空闲列表中寻找与本块相近的块
  261.         for (pPriv_Node = pRoot->pStart; pPriv_Node->next_node <pSrc_Node; pPriv_Node = pPriv_Node->next_node);
  262.         pNext_Node = pPriv_Node->next_node;

  263.         if (pNext_Node != pRoot->pEnd && \
  264.                 ((uint8_t*)src_addr + pSrc_Node->mem_size == (uint8_t*)pNext_Node) && \
  265.                 (pSrc_Node->mem_size + pNext_Node->mem_size + MEM_MANAGE_MEM_STRUCT_SIZE >= want_size)) {
  266.                 //满足下一节点非end,内存连续,内存剩余足够
  267.                 pReturn = src_addr;
  268.                 pPriv_Node->next_node = pNext_Node->next_node;//排出空闲列表
  269.                 pRoot->remain_size -= pNext_Node->mem_size;
  270.                 pSrc_Node->mem_size += MEM_MANAGE_MEM_STRUCT_SIZE + pNext_Node->mem_size;
  271.                 want_size = Mem_Manage_Align_Up(want_size, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  272.                 if (pSrc_Node->mem_size >= MEM_MANAGE_MINUM_NODE_SIZE+ want_size) {//去除分配的剩余空间足够开辟新块
  273.                         Mem_Node* pNew_Node = (Mem_Node*)((uint8_t*)Mem_Manage_Mem_To_Addr(pSrc_Node) + want_size);
  274.                         pNew_Node->next_node = NULL;
  275.                         pNew_Node->mem_size = pSrc_Node->mem_size - want_size - MEM_MANAGE_MEM_STRUCT_SIZE;
  276.                         pSrc_Node->mem_size = want_size;
  277.                         Mem_Insert_Node_To_FreeList(pRoot, pNew_Node);
  278.                 }
  279.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  280.         }
  281.         else {
  282.                 pReturn = Mem_Manage_Aligned_Alloc(pRoot, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT, want_size);
  283.                 if (pReturn == NULL){
  284.                         pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  285.                         return NULL;
  286.                 }
  287.                 memcpy(pReturn, src_addr, pSrc_Node->mem_size);
  288.                 pSrc_Node->mem_size |= MEM_MANAGE_ALLOCA_LABAL;//恢复分配标记
  289.                 Mem_Manage_Free(pRoot, src_addr);
  290.         }
  291.         return pReturn;
  292. }

  293. //与C库函数free作用一致
  294. //pRoot:句柄指针
  295. //addr:释放内存的首地址
  296. //return:无返回值
  297. void Mem_Manage_Free(Mem_Root* pRoot,void* addr) {
  298.         Mem_Node* pFree_Node;
  299.         
  300.         if(pRoot->err_flag!=MEM_NO_ERR){
  301.                 return;
  302.         }
  303.         
  304.         if(pRoot->pStart==NULL||pRoot->pEnd==NULL){
  305.                 pRoot->err_flag=MEM_NO_INIT;
  306.                 return;
  307.         }
  308.         
  309.         if (addr == NULL) {
  310.                 return;
  311.         }
  312.         pFree_Node = Mem_Manage_Addr_To_Mem(addr);

  313.         if ((pFree_Node->mem_size&MEM_MANAGE_ALLOCA_LABAL) == 0) {//释放错误,没有标记
  314.                 pRoot->err_flag=MEM_OVER_WRITE;
  315.                 return;
  316.         }

  317.         if (pFree_Node->next_node != NULL) {//释放错误
  318.                 pRoot->err_flag=MEM_OVER_WRITE;
  319.                 return;
  320.         }
  321.         pFree_Node->mem_size &= ~MEM_MANAGE_ALLOCA_LABAL;//清除分配标记
  322.         Mem_Insert_Node_To_FreeList(pRoot, pFree_Node);//插入到空闲链表中
  323. }

  324. //获取句柄管理的内存区总容量
  325. //pRoot:句柄指针
  326. //return:内存区总容量(单位:byte)
  327. size_t Mem_Manage_Get_Total_Size(const Mem_Root* pRoot){
  328.         return pRoot->total_size;
  329. }

  330. //获取句柄管理的内存区剩余容量
  331. //pRoot:句柄指针
  332. //return:内存区剩余容量(单位:byte)
  333. size_t Mem_Manage_Get_Remain_Size(const Mem_Root* pRoot){
  334.         return pRoot->remain_size;
  335. }

  336. //获取句柄管理的内存区错误标记
  337. //pRoot:句柄指针
  338. //return:错误标记
  339. Mem_Err_Type Mem_Manage_Get_Errflag(const Mem_Root* pRoot){
  340.         return pRoot->err_flag;
  341. }

  342. //内存管理句柄初始化
  343. //pRoot:句柄指针
  344. //pRigon:内存区结构体指针
  345. //return:        true 初始化成功;
  346. //                        false 初始化失败
  347. bool Mem_Manage_Init(Mem_Root* pRoot,const Mem_Region* pRegion) {
  348.         Mem_Node* align_addr;
  349.         size_t align_size;
  350.         Mem_Node* pPriv_node=NULL;

  351.         pRoot->total_size = 0;
  352.         pRoot->pEnd = NULL;
  353.         pRoot->pStart = NULL;
  354.         pRoot->err_flag = MEM_NO_INIT;
  355.         pRoot->remain_size = 0;
  356.         for (; pRegion->addr != NULL; pRegion++) {
  357.                 align_addr = (Mem_Node*)Mem_Manage_Align_Up((size_t)pRegion->addr, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);//计算内存块对齐后的地址
  358.                 if ((uint8_t*)align_addr > pRegion->mem_size+ (uint8_t*)pRegion->addr)//对齐消耗的内存超过内存区
  359.                         continue;
  360.                 align_size = pRegion->mem_size - ((uint8_t*)align_addr - (uint8_t*)pRegion->addr);//计算对齐后剩下的内存大小
  361.                 if (align_size < MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE)//对齐剩下的内存太小
  362.                         continue;
  363.                 align_size -= MEM_MANAGE_MEM_STRUCT_SIZE;//求除去掉表头后内存块的大小
  364.                 align_addr->mem_size = align_size;
  365.                 align_addr->next_node = NULL;
  366.                 if (pRoot->pStart == NULL) {//如果是初始化
  367.                         pRoot->pStart = align_addr;//将当前内存块地址记为start
  368.                         if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE+ MEM_MANAGE_MEM_STRUCT_SIZE) {//若剩下的块足够大
  369.                                 align_size -= MEM_MANAGE_MEM_STRUCT_SIZE;//去掉下一个块的表头剩下的内存大小
  370.                                 align_addr = (Mem_Node*)((uint8_t*)pRoot->pStart + MEM_MANAGE_MEM_STRUCT_SIZE);//下一个块的表头地址
  371.                                 align_addr->mem_size = align_size;
  372.                                 align_addr->next_node = NULL;
  373.                                 pRoot->pStart->mem_size = 0;
  374.                                 pRoot->pStart->next_node = align_addr;
  375.                                 pRoot->total_size = align_addr->mem_size;
  376.                         }
  377.                         else {//内存太小了,将当前内存块地址记为start
  378.                                 pRoot->total_size = 0;
  379.                                 pRoot->pStart->mem_size = 0;
  380.                         }
  381.                 }
  382.                 else {
  383.                         if (pPriv_node == NULL) {
  384.                                 pRoot->err_flag = MEM_NO_INIT;
  385.                                 return false;
  386.                         }
  387.                         pPriv_node->next_node = align_addr;//更新上一节点的next_node
  388.                         pRoot->total_size += align_size;
  389.                 }
  390.                 pPriv_node = align_addr;
  391.         }
  392.         if (pPriv_node == NULL) {
  393.                 pRoot->err_flag = MEM_NO_INIT;
  394.                 return false;
  395.         }
  396.         //此时,pPriv_node为最后一个块,接下来在块尾放置表尾end
  397.         //求出放置end块的地址,end块仅是方便遍历使用,因此尽量小,分配为MEM_MANAGE_MEM_STRUCT_SIZE
  398.         align_addr = (Mem_Node*)Mem_Manage_Align_Down(\
  399.                 (size_t)Mem_Manage_Mem_To_Addr(pPriv_node) + pPriv_node->mem_size - MEM_MANAGE_MEM_STRUCT_SIZE, MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  400.         align_size = (uint8_t*)align_addr-(uint8_t*)Mem_Manage_Mem_To_Addr(pPriv_node);//求出分配出end块后,前一个块剩余大小
  401.         if (align_size >= MEM_MANAGE_MINUM_MEM_SIZE) {//若剩下的块足够大
  402.                 pRoot->total_size -= pPriv_node->mem_size - align_size;//去掉分配end块消耗的内存
  403.                 pRoot->pEnd = align_addr;                        //更新表尾的地址
  404.                 pPriv_node->next_node = align_addr;
  405.                 pPriv_node->mem_size = align_size;
  406.                 align_addr->next_node = NULL;
  407.                 align_addr->mem_size = 0;//end块不参与内存分配,因此直接为0就可以
  408.         }
  409.         else {//最后一个块太小了,直接作为end块
  410.                 pRoot->pEnd = pPriv_node;
  411.                 pRoot->total_size -= pPriv_node->mem_size;
  412.         }
  413.         if(pRoot->pStart==NULL||pRoot->pEnd==NULL){
  414.                 pRoot->err_flag=MEM_NO_INIT;
  415.                 return false;
  416.         }
  417.         Mem_Settle(pRoot);
  418.         pRoot->err_flag=MEM_NO_ERR;
  419.         pRoot->remain_size=pRoot->total_size;
  420.         return true;
  421. }

  422. //内存池初始化
  423. //mem_addr:内存池首地址
  424. //mem_size:内存池大小
  425. //return:        true 初始化成功;
  426. //                        false 初始化失败
  427. bool Mem_Manage_Pool_Init(void* mem_addr,size_t mem_size){
  428.         void* paddr=(uint8_t*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT)+MEM_MANAGE_MEM_ROOT_SIZE;
  429.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  430.         size_t align_size=(uint8_t*)paddr-(uint8_t*)mem_addr;
  431.         Mem_Region buf_region[]={
  432.                 0,0,
  433.                 NULL,0
  434.         };
  435.         if(mem_size<align_size)
  436.                 return 0;
  437.         mem_size-=align_size;
  438.         if(mem_size<2*MEM_MANAGE_MEM_STRUCT_SIZE+MEM_MANAGE_MINUM_NODE_SIZE)
  439.                 return 0;
  440.         buf_region[0].addr=paddr;
  441.         buf_region[0].mem_size=mem_size;
  442.         return Mem_Manage_Init(root_addr,buf_region);
  443. }

  444. //与C库函数malloc作用相同
  445. //mem_addr:内存池首地址
  446. //want_size:期望分配内存大小
  447. //return:        NULL 分配失败(内存不足或者错误标记不为MEM_NO_ERR);
  448. //                        其他值 分配成功
  449. void* Mem_Manage_Pool_Malloc(void* mem_addr,size_t want_size){
  450.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  451.         return Mem_Manage_Malloc(root_addr,want_size);
  452. }

  453. //与C库函数realloc作用相同
  454. //mem_addr:内存池首地址
  455. //src_addr:源地址指针
  456. //want_size:期望分配内存大小
  457. //return:        NULL 分配失败(内存不足或者错误标记不为MEM_NO_ERR);
  458. //                        其他值 分配成功
  459. void* Mem_Manage_Pool_Realloc(void* mem_addr,void* src_addr,size_t want_size){
  460.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  461.         return Mem_Manage_Realloc(root_addr,src_addr,want_size);
  462. }

  463. //与C库函数aligned_alloc作用一致
  464. //mem_addr:内存池首地址
  465. //align_size:期望分配的内存几字节对齐(8、16、32...)
  466. //want_size:期望分配内存大小
  467. //return:        NULL 分配失败(内存不足或者句柄错误标记不为MEM_NO_ERR);
  468. //                        其他值 分配成功
  469. void* Mem_Manage_Pool_Aligned_Alloc(void* mem_addr,size_t align_byte,size_t want_size){
  470.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  471.         return Mem_Manage_Aligned_Alloc(root_addr,align_byte,want_size);
  472. }

  473. //与C库函数free作用一致
  474. //mem_addr:内存池首地址
  475. //free_addr:释放内存的首地址
  476. //return:无返回值
  477. void Mem_Manage_Pool_Free(void* mem_addr,void* free_addr){
  478.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  479.         Mem_Manage_Free(root_addr,free_addr);
  480. }

  481. //获取内存池的状态
  482. //mem_addr:内存池首地址
  483. //pState:状态信息结构体指针
  484. //return:无返回值
  485. void Mem_Manage_Pool_Get_State(void* mem_addr,Mem_State* pState){
  486.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  487.         Mem_Manage_Get_State(root_addr,pState);
  488. }

  489. //获取内存池总容量
  490. //mem_addr:内存池首地址
  491. //return:内存区总容量(单位:byte)
  492. size_t Mem_Manage_Pool_Get_Total_Size(const void* mem_addr){
  493.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  494.         return Mem_Manage_Get_Total_Size(root_addr);
  495. }

  496. //获取内存池剩余容量
  497. //mem_addr:内存池首地址
  498. //return:内存区剩余容量(单位:byte)
  499. size_t Mem_Manage_Pool_Get_Remain_Size(const void* mem_addr){
  500.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  501.         return Mem_Manage_Get_Remain_Size(root_addr);
  502. }

  503. //获取内存池错误标记
  504. //mem_addr:内存池首地址
  505. //return:错误标记
  506. Mem_Err_Type Mem_Manage_Pool_Get_Errflag(const void* mem_addr){
  507.         Mem_Root* root_addr=(Mem_Root*)Mem_Manage_Align_Up((size_t)mem_addr,MEM_MANAGE_ALIGNMENT_BYTE_DEFAULT);
  508.         return Mem_Manage_Get_Errflag(root_addr);
  509. }


复制代码



评分

参与人数 6金币 +182 收起 理由
woodzn + 20 神马都是浮云
yunqi + 20 很给力!
nikola + 20 很给力!
SeanX + 2 赞一个!
812126060 + 20
eric2013 + 100 很给力!

查看全部评分

回复

使用道具 举报

210

主题

1041

回帖

1681

积分

至尊会员

More we do, more we can do.

积分
1681
发表于 2021-9-3 15:02:30 | 显示全部楼层
看简介很厉害,设计原理文档有吗?拜读一下
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-3 17:50:08 | 显示全部楼层
emwin 发表于 2021-9-3 15:02
看简介很厉害,设计原理文档有吗?拜读一下

有文档的,我把它发在帖子的回复里
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-3 17:51:44 | 显示全部楼层
本算法的实现原理及测试工程

内存管理设计文档.pdf

249.98 KB, 下载次数: 407

回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-3 17:53:57 | 显示全部楼层
本算法的实现原理及测试工程

内存管理设计文档.pdf

249.98 KB, 下载次数: 122

回复

使用道具 举报

608

主题

3038

回帖

4882

积分

至尊会员

积分
4882
发表于 2021-9-4 11:49:11 | 显示全部楼层
貌似这一版本,吧信号量给取消了
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106437
QQ
发表于 2021-9-4 15:51:28 | 显示全部楼层
谢谢楼主分享。
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-4 21:41:02 | 显示全部楼层
hpdell 发表于 2021-9-4 11:49
貌似这一版本,吧信号量给取消了

把原来的钩子函数什么的都取消掉了,感觉实际意义不大,这一版主要增加了内存池方式管理内存空间的函数
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-11 13:03:13 | 显示全部楼层
eric2013 发表于 2021-9-4 15:51
谢谢楼主分享。

回复

使用道具 举报

3

主题

12

回帖

21

积分

新手上路

积分
21
发表于 2021-9-20 22:54:53 | 显示全部楼层
学习学习  正好需要一个好的内存管理算法
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-9-28 19:14:07 | 显示全部楼层
812126060 发表于 2021-9-20 22:54
学习学习  正好需要一个好的内存管理算法

欢迎交流
回复

使用道具 举报

2

主题

39

回帖

45

积分

新手上路

积分
45
发表于 2021-11-9 16:42:23 | 显示全部楼层
厉害,之前的1.1用到了项目中,使用环境没有频繁的内存申请和释放,能直接升级V1.2吗
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-11-14 20:27:06 | 显示全部楼层
落叶凋零 发表于 2021-11-9 16:42
厉害,之前的1.1用到了项目中,使用环境没有频繁的内存申请和释放,能直接升级V1.2吗

可以直接升级,原来版本的在使用方便性上有点问题,v1.1和v1.2内部的内存分配策略都是没问题的
回复

使用道具 举报

7

主题

190

回帖

216

积分

高级会员

积分
216
发表于 2021-11-15 09:51:03 | 显示全部楼层
楼主 这个能用来管理外部spiflash嘛
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2021-11-15 15:11:46 | 显示全部楼层
abcde1224 发表于 2021-11-15 09:51
楼主 这个能用来管理外部spiflash嘛

这个不适合管理spiflash哦,只适合管理ram的内存,功能与c库函数中的malloc相似
回复

使用道具 举报

5

主题

95

回帖

110

积分

初级会员

积分
110
发表于 2021-12-5 23:36:37 | 显示全部楼层
回复

使用道具 举报

0

主题

34

回帖

34

积分

新手上路

积分
34
发表于 2021-12-6 16:03:55 | 显示全部楼层
多谢楼主分享,先顶再看!
回复

使用道具 举报

1

主题

30

回帖

33

积分

新手上路

积分
33
发表于 2022-2-16 10:57:59 | 显示全部楼层
mark                  
回复

使用道具 举报

0

主题

1

回帖

1

积分

新手上路

积分
1
发表于 2022-2-16 12:07:29 | 显示全部楼层
准备移植到项目里
回复

使用道具 举报

1

主题

30

回帖

33

积分

新手上路

积分
33
发表于 2022-4-18 22:56:26 | 显示全部楼层
mark                  
回复

使用道具 举报

4

主题

19

回帖

31

积分

新手上路

积分
31
发表于 2022-4-29 17:51:36 | 显示全部楼层
#define MEM_MANAGE_ALLOCA_LABAL                                        ((size_t)((size_t)1<<(sizeof(size_t)*MEM_MANAGE_BITS_PER_BYTE-1)))这么写能避免些警告,强迫症,看不得警告.....
回复

使用道具 举报

19

主题

62

回帖

119

积分

初级会员

积分
119
发表于 2022-6-2 15:53:30 | 显示全部楼层
内存池和内存有啥区别?
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2022-6-4 20:40:41 | 显示全部楼层
mojinpan 发表于 2022-6-2 15:53
内存池和内存有啥区别?

没啥区别,内存池使用更无脑一点
回复

使用道具 举报

6

主题

8

回帖

26

积分

新手上路

积分
26
发表于 2022-6-10 15:36:03 | 显示全部楼层
什么项目上才会用到啊?没碰到过用需要内存管理的项目
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2022-7-26 14:53:19 | 显示全部楼层
本帖最后由 SeanX 于 2022-7-26 15:33 编辑

回复

使用道具 举报

1

主题

22

回帖

25

积分

新手上路

积分
25
发表于 2023-4-27 13:51:48 | 显示全部楼层

所以該方法,比RTX5 更能有效管理是嗎?
__WEAK void *osRtxMemoryAlloc (void *mem, uint32_t size, uint32_t type)
還是可以混合用?
回复

使用道具 举报

12

主题

153

回帖

204

积分

高级会员

积分
204
 楼主| 发表于 2023-5-2 19:44:55 | 显示全部楼层
James2jian 发表于 2023-4-27 13:51
所以該方法,比RTX5 更能有效管理是嗎?
__WEAK void *osRtxMemoryAlloc (void *mem, uint32_t size, uin ...

不能混合用,我这个主要的优势是可以将零散的内存合并管理
回复

使用道具 举报

608

主题

3038

回帖

4882

积分

至尊会员

积分
4882
发表于 2023-7-14 09:20:50 | 显示全部楼层
WZH 发表于 2023-5-2 19:44
不能混合用,我这个主要的优势是可以将零散的内存合并管理

搞一个 通用函数进行宏定义就可以了
回复

使用道具 举报

1

主题

11

回帖

14

积分

新手上路

积分
14
发表于 2023-7-19 15:45:58 | 显示全部楼层
回复

使用道具 举报

0

主题

2

回帖

2

积分

新手上路

积分
2
发表于 2023-9-15 18:07:08 | 显示全部楼层
怎么复制代码?
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-4-21 00:05 , Processed in 0.296009 second(s), 29 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

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