RT-Thread学习2 —— 内存管理学习记录1

小内存管理算法(mem.c)

1. 小内存管理法:

小内存管理算法是一个简单的内存分配算法。初始时,它是一块大的内存。当需要分配内存块时,将从这个大的内存块上分割出相匹配的内存块,然后把分割出来的空闲内存块还回给堆管理系统中。每个内存块都包含一个管理用的数据头,通过这个头把使用块与空闲块用双向链表的方式链接起来,如下图所示:

2. 两大数据结构体



rt_samll_mem:记录整个内存对象的基本信息

rt_samll_mem_item:记录各个内存块的使用情况

3. 初始化函数:rt_smem_init

在函数参数合法的情况下执行后的初始化内存结构大致如下图所示:

4. rt_smem_alloc函数和rt_smem_realloc函数


  1. /**
  2. * @brief Allocate a block of memory with a minimum of 'size' bytes.
  3. *
  4. * @param m the small memory management object.
  5. *
  6. * @param size is the minimum size of the requested block in bytes.
  7. *
  8. * @return the pointer to allocated memory or NULL if no free memory was found.
  9. */
  10. void *rt_smem_alloc(rt_smem_t m, rt_size_t size)
  11. {
  12. rt_size_t ptr, ptr2;
  13. struct rt_small_mem_item *mem, *mem2;
  14. struct rt_small_mem *small_mem;
  15. if (size == 0)
  16. return RT_NULL;
  17. RT_ASSERT(m != RT_NULL);
  18. RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory);
  19. RT_ASSERT(rt_object_is_systemobject(&m->parent));
  20. if (size != RT_ALIGN(size, RT_ALIGN_SIZE))
  21. RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d, but align to %d\n",
  22. size, RT_ALIGN(size, RT_ALIGN_SIZE)));
  23. else
  24. RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d\n", size));
  25. small_mem = (struct rt_small_mem *)m;
  26. /* alignment size */
  27. size = RT_ALIGN(size, RT_ALIGN_SIZE);
  28. //判断申请的空间是不是大于整个内存的空间
  29. if (size > small_mem->mem_size_aligned)
  30. {
  31. RT_DEBUG_LOG(RT_DEBUG_MEM, ("no memory\n"));
  32. return RT_NULL;
  33. }
  34. //确保申请的空间最小是对齐size的大小
  35. /* every data block must be at least MIN_SIZE_ALIGNED long */
  36. if (size < MIN_SIZE_ALIGNED)
  37. size = MIN_SIZE_ALIGNED;
  38. //遍历每一个item
  39. for (ptr = (rt_uint8_t *)small_mem->lfree - small_mem->heap_ptr;
  40. ptr <= small_mem->mem_size_aligned - size;
  41. ptr = ((struct rt_small_mem_item *)&small_mem->heap_ptr[ptr])->next)
  42. {
  43. mem = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr];
  44. //找空闲块并且这个空闲块的大小比要申请的大的块
  45. if ((!MEM_ISUSED(mem)) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size)
  46. {
  47. /* mem is not used and at least perfect fit is possible:
  48. * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */
  49. //如果当前的item后面跟的内存块比要申请的空间加其他描述信息的空间大,那就符合条件
  50. if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >=
  51. (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED))
  52. {
  53. /* (in addition to the above, we test if another struct rt_small_mem_item (SIZEOF_STRUCT_MEM) containing
  54. * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem')
  55. * -> split large block, create empty remainder,
  56. * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if
  57. * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size,
  58. * struct rt_small_mem_item would fit in but no data between mem2 and mem2->next
  59. * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty
  60. * region that couldn't hold data, but when mem->next gets freed,
  61. * the 2 regions would be combined, resulting in more free memory
  62. */
  63. //ptr2 指向当前信息块加实际内存块后的地址(下一个空闲块要写入对应的信息块)
  64. ptr2 = ptr + SIZEOF_STRUCT_MEM + size;
  65. //mem2为下一个信息块赋值
  66. /* create mem2 struct */
  67. mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2];
  68. mem2->pool_ptr = MEM_FREED();
  69. mem2->next = mem->next;
  70. mem2->prev = ptr;
  71. #ifdef RT_USING_MEMTRACE
  72. rt_smem_setname(mem2, " ");
  73. #endif /* RT_USING_MEMTRACE */
  74. //设置当前信息块的下一个为pt2
  75. /* and insert it between mem and mem->next */
  76. mem->next = ptr2;
  77. //如果不是初始时候的第一块那需要把end of heap的pre指向ptr2
  78. if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM)
  79. {
  80. ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2;
  81. }
  82. small_mem->parent.used += (size + SIZEOF_STRUCT_MEM);
  83. if (small_mem->parent.max < small_mem->parent.used)
  84. small_mem->parent.max = small_mem->parent.used;
  85. }
  86. else
  87. {
  88. /* (a mem2 struct does no fit into the user data space of mem and mem->next will always
  89. * be used at this point: if not we have 2 unused structs in a row, plug_holes should have
  90. * take care of this).
  91. * -> near fit or excact fit: do not split, no mem2 creation
  92. * also can't move mem->next directly behind mem, since mem->next
  93. * will always be used at this point!
  94. */
  95. //如果不够长,将位置占上
  96. small_mem->parent.used += mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr);
  97. if (small_mem->parent.max < small_mem->parent.used)
  98. small_mem->parent.max = small_mem->parent.used;
  99. }
  100. //设置当前要申请的内存的信息块
  101. /* set small memory object */
  102. mem->pool_ptr = MEM_USED();
  103. #ifdef RT_USING_MEMTRACE
  104. if (rt_thread_self())
  105. rt_smem_setname(mem, rt_thread_self()->name);
  106. else
  107. rt_smem_setname(mem, "NONE");
  108. #endif /* RT_USING_MEMTRACE */
  109. //将lfree指向下一个空闲的位置
  110. if (mem == small_mem->lfree)
  111. {
  112. /* Find next free block after mem and update lowest free pointer */
  113. while (MEM_ISUSED(small_mem->lfree) && small_mem->lfree != small_mem->heap_end)
  114. small_mem->lfree = (struct rt_small_mem_item *)&small_mem->heap_ptr[small_mem->lfree->next];
  115. RT_ASSERT(((small_mem->lfree == small_mem->heap_end) || (!MEM_ISUSED(small_mem->lfree))));
  116. }
  117. RT_ASSERT((rt_ubase_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_ubase_t)small_mem->heap_end);
  118. RT_ASSERT((rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE == 0);
  119. RT_ASSERT((((rt_ubase_t)mem) & (RT_ALIGN_SIZE - 1)) == 0);
  120. RT_DEBUG_LOG(RT_DEBUG_MEM,
  121. ("allocate memory at 0x%x, size: %d\n",
  122. (rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM),
  123. (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr))));
  124. //返回的是真实可以操作数据的地址(前面会又一个信息头)
  125. /* return the memory data except mem struct */
  126. return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM;
  127. }
  128. }
  129. return RT_NULL;
  130. }

  1. /**
  2. * @brief This function will change the size of previously allocated memory block.
  3. *
  4. * @param m the small memory management object.
  5. *
  6. * @param rmem is the pointer to memory allocated by rt_mem_alloc.
  7. *
  8. * @param newsize is the required new size.
  9. *
  10. * @return the changed memory block address.
  11. */
  12. void *rt_smem_realloc(rt_smem_t m, void *rmem, rt_size_t newsize)
  13. {
  14. rt_size_t size;
  15. rt_size_t ptr, ptr2;
  16. struct rt_small_mem_item *mem, *mem2;
  17. struct rt_small_mem *small_mem;
  18. void *nmem;
  19. RT_ASSERT(m != RT_NULL);
  20. RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory);
  21. RT_ASSERT(rt_object_is_systemobject(&m->parent));
  22. small_mem = (struct rt_small_mem *)m;
  23. /* alignment size */
  24. newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
  25. //新申请的比总空间大
  26. if (newsize > small_mem->mem_size_aligned)
  27. {
  28. RT_DEBUG_LOG(RT_DEBUG_MEM, ("realloc: out of memory\n"));
  29. return RT_NULL;
  30. }
  31. //新申请的大小是0
  32. else if (newsize == 0)
  33. {
  34. rt_smem_free(rmem);
  35. return RT_NULL;
  36. }
  37. //地址还没allocate
  38. /* allocate a new memory block */
  39. if (rmem == RT_NULL)
  40. return rt_smem_alloc(&small_mem->parent, newsize);
  41. RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0);
  42. RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr);
  43. RT_ASSERT((rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end);
  44. //取出申请内存的信息块
  45. mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM);
  46. //计算当前信息块的大小
  47. /* current memory block size */
  48. ptr = (rt_uint8_t *)mem - small_mem->heap_ptr;
  49. size = mem->next - ptr - SIZEOF_STRUCT_MEM;
  50. if (size == newsize)
  51. {
  52. /* the size is the same as */
  53. return rmem;
  54. }
  55. //当前信息块比新申请的大
  56. if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size)
  57. {
  58. /* split memory block */
  59. small_mem->parent.used -= (size - newsize);
  60. ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize;
  61. mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2];
  62. mem2->pool_ptr = MEM_FREED();
  63. mem2->next = mem->next;
  64. mem2->prev = ptr;
  65. #ifdef RT_USING_MEMTRACE
  66. rt_smem_setname(mem2, " ");
  67. #endif /* RT_USING_MEMTRACE */
  68. mem->next = ptr2;
  69. if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM)
  70. {
  71. ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2;
  72. }
  73. if (mem2 < small_mem->lfree)
  74. {
  75. /* the splited struct is now the lowest */
  76. small_mem->lfree = mem2;
  77. }
  78. plug_holes(small_mem, mem2);
  79. return rmem;
  80. }
  81. /* expand memory */
  82. nmem = rt_smem_alloc(&small_mem->parent, newsize);
  83. if (nmem != RT_NULL) /* check memory */
  84. {
  85. rt_memcpy(nmem, rmem, size < newsize ? size : newsize);
  86. rt_smem_free(rmem);
  87. }
  88. return nmem;
  89. }
  90. RTM_EXPORT(rt_smem_realloc);

RT-Thread学习2 —— 内存管理学习记录的更多相关文章

  1. java虚拟机学习-JVM内存管理:深入Java内存区域与OOM(3)

    概述 Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 对于从事C.C++程序开发的开发人员来说,在内存管理领域,他们即是拥有最高权力的皇帝又 ...

  2. C++内存管理学习笔记(5)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  3. C++内存管理学习笔记(7)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  4. C++内存管理学习笔记(6)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  5. java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)

    Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...

  6. python学习Day9 内存管理

    复习 :文件处理 1. 操作文件的三步骤:-- 打开文件:此时该文件在硬盘的空间被操作系统持有 |  文件对象被应用程序持用 -- 操作文件:读写操作 -- 释放文件:释放操作系统对文件在硬盘间的持有 ...

  7. Linux内存管理学习资料

    下面是Linux内存管理学习的一些资料. 博客 mlock() and mlockall() system calls. All about Linux swap space 逆向映射的演进 Linu ...

  8. C++内存管理学习笔记(4)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  9. C++内存管理学习笔记(3)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

随机推荐

  1. Go 学习路线(2022)

    原文链接: Go 学习路线(2022) Go 语言的发展越来越好了,很多大厂使用 Go 作为主要开发语言,也有很多人开始学习 Go,准备转 Go 开发. 那么,怎么学呢? 我发现,在互联网时代,学习的 ...

  2. Td 内容不换行,超过部分自动截断,用...表示

    转载请注明来源:https://www.cnblogs.com/hookjc/ <table width="200px" style="table-layout:f ...

  3. VC中如何将资源打包并释放到指定文件夹

    转载请注明来源:https://www.cnblogs.com/hookjc/ 很多时候,我们可能要将某些文件打包到资源中,然后当程序执行的时候,发现缺少某些文件时,进行自我修复,以维持程序的正常执行 ...

  4. 用最笨的方法实现java控制台日历打印

    如果想用户自定义输入日期查询,可以通过Calendar的set方法和Scanner方法设置 Calendar类简单使用:https://blog.csdn.net/weixin_43670802/ar ...

  5. AndroidStudio项目提交到github最详细步骤【转】

    感谢大佬:https://www.cnblogs.com/imqsl/p/6763133.html 在使用studio开发的项目过程中有时候我们想将项目发布到github上,以前都是用一种比较麻烦的方 ...

  6. 诗和远方-target

    学习也是这样:不以结婚为目的的谈恋爱,都是耍流氓!

  7. SqlServer数据库表生成C# Model实体类SQL语句——补充

    在sql语句最前边加上  use[数据库名] 原链接:https://www.cnblogs.com/jhli/p/11552105.html   --[SQL骚操作]SqlServer数据库表生成C ...

  8. 【转】Python中自定义可迭代对象

    python 中内置的可迭代的对象有 list.tuple.set.dict 等,那么我们自己怎么定义一个可迭代的对象呢?先来段代码吧 import re import reprlib RE_WORD ...

  9. android+json+php+mysql实现用户反馈功能

    相信每个项目都会有用户反馈建议等功能,这个实现的方法很多,下面是我实现的方法,供大家交流.首先看具体界面,三个字段.名字,邮箱为选填,可以为空,建议不能为空.如有需要可以给我留言. 下面贴出布局代码, ...

  10. 2022寒假集训day4

    day4(day5补完的) 继续刷搜索方面的题, 初步了解了序列. T1 迷宫问题 题目描述设有一个 n*n 方格的迷宫,入口和出口分别在左上角和右上角.迷宫格子中分别放 0 和 1 ,0 表示可通, ...