RT-Thread学习2 —— 内存管理学习记录
2022/3/9 7:17:10
本文主要是介绍RT-Thread学习2 —— 内存管理学习记录,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
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函数
/** * @brief Allocate a block of memory with a minimum of 'size' bytes. * * @param m the small memory management object. * * @param size is the minimum size of the requested block in bytes. * * @return the pointer to allocated memory or NULL if no free memory was found. */ void *rt_smem_alloc(rt_smem_t m, rt_size_t size) { rt_size_t ptr, ptr2; struct rt_small_mem_item *mem, *mem2; struct rt_small_mem *small_mem; if (size == 0) return RT_NULL; RT_ASSERT(m != RT_NULL); RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory); RT_ASSERT(rt_object_is_systemobject(&m->parent)); if (size != RT_ALIGN(size, RT_ALIGN_SIZE)) RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d, but align to %d\n", size, RT_ALIGN(size, RT_ALIGN_SIZE))); else RT_DEBUG_LOG(RT_DEBUG_MEM, ("malloc size %d\n", size)); small_mem = (struct rt_small_mem *)m; /* alignment size */ size = RT_ALIGN(size, RT_ALIGN_SIZE); //判断申请的空间是不是大于整个内存的空间 if (size > small_mem->mem_size_aligned) { RT_DEBUG_LOG(RT_DEBUG_MEM, ("no memory\n")); return RT_NULL; } //确保申请的空间最小是对齐size的大小 /* every data block must be at least MIN_SIZE_ALIGNED long */ if (size < MIN_SIZE_ALIGNED) size = MIN_SIZE_ALIGNED; //遍历每一个item for (ptr = (rt_uint8_t *)small_mem->lfree - small_mem->heap_ptr; ptr <= small_mem->mem_size_aligned - size; ptr = ((struct rt_small_mem_item *)&small_mem->heap_ptr[ptr])->next) { mem = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr]; //找空闲块并且这个空闲块的大小比要申请的大的块 if ((!MEM_ISUSED(mem)) && (mem->next - (ptr + SIZEOF_STRUCT_MEM)) >= size) { /* mem is not used and at least perfect fit is possible: * mem->next - (ptr + SIZEOF_STRUCT_MEM) gives us the 'user data size' of mem */ //如果当前的item后面跟的内存块比要申请的空间加其他描述信息的空间大,那就符合条件 if (mem->next - (ptr + SIZEOF_STRUCT_MEM) >= (size + SIZEOF_STRUCT_MEM + MIN_SIZE_ALIGNED)) { /* (in addition to the above, we test if another struct rt_small_mem_item (SIZEOF_STRUCT_MEM) containing * at least MIN_SIZE_ALIGNED of data also fits in the 'user data space' of 'mem') * -> split large block, create empty remainder, * remainder must be large enough to contain MIN_SIZE_ALIGNED data: if * mem->next - (ptr + (2*SIZEOF_STRUCT_MEM)) == size, * struct rt_small_mem_item would fit in but no data between mem2 and mem2->next * @todo we could leave out MIN_SIZE_ALIGNED. We would create an empty * region that couldn't hold data, but when mem->next gets freed, * the 2 regions would be combined, resulting in more free memory */ //ptr2 指向当前信息块加实际内存块后的地址(下一个空闲块要写入对应的信息块) ptr2 = ptr + SIZEOF_STRUCT_MEM + size; //mem2为下一个信息块赋值 /* create mem2 struct */ mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2]; mem2->pool_ptr = MEM_FREED(); mem2->next = mem->next; mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_smem_setname(mem2, " "); #endif /* RT_USING_MEMTRACE */ //设置当前信息块的下一个为pt2 /* and insert it between mem and mem->next */ mem->next = ptr2; //如果不是初始时候的第一块那需要把end of heap的pre指向ptr2 if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM) { ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2; } small_mem->parent.used += (size + SIZEOF_STRUCT_MEM); if (small_mem->parent.max < small_mem->parent.used) small_mem->parent.max = small_mem->parent.used; } else { /* (a mem2 struct does no fit into the user data space of mem and mem->next will always * be used at this point: if not we have 2 unused structs in a row, plug_holes should have * take care of this). * -> near fit or excact fit: do not split, no mem2 creation * also can't move mem->next directly behind mem, since mem->next * will always be used at this point! */ //如果不够长,将位置占上 small_mem->parent.used += mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr); if (small_mem->parent.max < small_mem->parent.used) small_mem->parent.max = small_mem->parent.used; } //设置当前要申请的内存的信息块 /* set small memory object */ mem->pool_ptr = MEM_USED(); #ifdef RT_USING_MEMTRACE if (rt_thread_self()) rt_smem_setname(mem, rt_thread_self()->name); else rt_smem_setname(mem, "NONE"); #endif /* RT_USING_MEMTRACE */ //将lfree指向下一个空闲的位置 if (mem == small_mem->lfree) { /* Find next free block after mem and update lowest free pointer */ while (MEM_ISUSED(small_mem->lfree) && small_mem->lfree != small_mem->heap_end) small_mem->lfree = (struct rt_small_mem_item *)&small_mem->heap_ptr[small_mem->lfree->next]; RT_ASSERT(((small_mem->lfree == small_mem->heap_end) || (!MEM_ISUSED(small_mem->lfree)))); } RT_ASSERT((rt_ubase_t)mem + SIZEOF_STRUCT_MEM + size <= (rt_ubase_t)small_mem->heap_end); RT_ASSERT((rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM) % RT_ALIGN_SIZE == 0); RT_ASSERT((((rt_ubase_t)mem) & (RT_ALIGN_SIZE - 1)) == 0); RT_DEBUG_LOG(RT_DEBUG_MEM, ("allocate memory at 0x%x, size: %d\n", (rt_ubase_t)((rt_uint8_t *)mem + SIZEOF_STRUCT_MEM), (rt_ubase_t)(mem->next - ((rt_uint8_t *)mem - small_mem->heap_ptr)))); //返回的是真实可以操作数据的地址(前面会又一个信息头) /* return the memory data except mem struct */ return (rt_uint8_t *)mem + SIZEOF_STRUCT_MEM; } } return RT_NULL; }
/** * @brief This function will change the size of previously allocated memory block. * * @param m the small memory management object. * * @param rmem is the pointer to memory allocated by rt_mem_alloc. * * @param newsize is the required new size. * * @return the changed memory block address. */ void *rt_smem_realloc(rt_smem_t m, void *rmem, rt_size_t newsize) { rt_size_t size; rt_size_t ptr, ptr2; struct rt_small_mem_item *mem, *mem2; struct rt_small_mem *small_mem; void *nmem; RT_ASSERT(m != RT_NULL); RT_ASSERT(rt_object_get_type(&m->parent) == RT_Object_Class_Memory); RT_ASSERT(rt_object_is_systemobject(&m->parent)); small_mem = (struct rt_small_mem *)m; /* alignment size */ newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE); //新申请的比总空间大 if (newsize > small_mem->mem_size_aligned) { RT_DEBUG_LOG(RT_DEBUG_MEM, ("realloc: out of memory\n")); return RT_NULL; } //新申请的大小是0 else if (newsize == 0) { rt_smem_free(rmem); return RT_NULL; } //地址还没allocate /* allocate a new memory block */ if (rmem == RT_NULL) return rt_smem_alloc(&small_mem->parent, newsize); RT_ASSERT((((rt_ubase_t)rmem) & (RT_ALIGN_SIZE - 1)) == 0); RT_ASSERT((rt_uint8_t *)rmem >= (rt_uint8_t *)small_mem->heap_ptr); RT_ASSERT((rt_uint8_t *)rmem < (rt_uint8_t *)small_mem->heap_end); //取出申请内存的信息块 mem = (struct rt_small_mem_item *)((rt_uint8_t *)rmem - SIZEOF_STRUCT_MEM); //计算当前信息块的大小 /* current memory block size */ ptr = (rt_uint8_t *)mem - small_mem->heap_ptr; size = mem->next - ptr - SIZEOF_STRUCT_MEM; if (size == newsize) { /* the size is the same as */ return rmem; } //当前信息块比新申请的大 if (newsize + SIZEOF_STRUCT_MEM + MIN_SIZE < size) { /* split memory block */ small_mem->parent.used -= (size - newsize); ptr2 = ptr + SIZEOF_STRUCT_MEM + newsize; mem2 = (struct rt_small_mem_item *)&small_mem->heap_ptr[ptr2]; mem2->pool_ptr = MEM_FREED(); mem2->next = mem->next; mem2->prev = ptr; #ifdef RT_USING_MEMTRACE rt_smem_setname(mem2, " "); #endif /* RT_USING_MEMTRACE */ mem->next = ptr2; if (mem2->next != small_mem->mem_size_aligned + SIZEOF_STRUCT_MEM) { ((struct rt_small_mem_item *)&small_mem->heap_ptr[mem2->next])->prev = ptr2; } if (mem2 < small_mem->lfree) { /* the splited struct is now the lowest */ small_mem->lfree = mem2; } plug_holes(small_mem, mem2); return rmem; } /* expand memory */ nmem = rt_smem_alloc(&small_mem->parent, newsize); if (nmem != RT_NULL) /* check memory */ { rt_memcpy(nmem, rmem, size < newsize ? size : newsize); rt_smem_free(rmem); } return nmem; } RTM_EXPORT(rt_smem_realloc);
这篇关于RT-Thread学习2 —— 内存管理学习记录的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南