1。新增双语文档。
This commit is contained in:
233
document/mem_manager/mem_manager.md
Normal file
233
document/mem_manager/mem_manager.md
Normal file
@@ -0,0 +1,233 @@
|
||||
# 动态内存管理
|
||||
|
||||
[English](mem_manager_EN.md)
|
||||
|
||||
<!-- TOC -->
|
||||
* [动态内存管理](#动态内存管理)
|
||||
* [主要功能:](#主要功能)
|
||||
* [内存合并的思路](#内存合并的思路)
|
||||
* [前合并的情况:](#前合并的情况)
|
||||
* [后合并的情况:](#后合并的情况)
|
||||
* [不合并的情况:](#不合并的情况)
|
||||
* [创建内存数组](#创建内存数组)
|
||||
* [创建内存管理结构体](#创建内存管理结构体)
|
||||
* [初始化内存管理](#初始化内存管理)
|
||||
* [分配内存](#分配内存)
|
||||
* [释放内存](#释放内存)
|
||||
* [插入内存块](#插入内存块)
|
||||
<!-- TOC -->
|
||||
|
||||
## 主要功能:
|
||||
- 内存块的动态分配 - 根据应用的请求,从未分配内存块中选择一个块进行分配。
|
||||
- 内存块的释放回收 - 当块不再需要时,将其释放并标记为未分配状态。
|
||||
- 已分配与未分配块记录 - 使用链表或数组等数据结构实时跟踪各状态块的信息。
|
||||
- 内存块合并 - 在释放块后,检查相邻块状态,若均未分配则合并为一个大块减少碎片。
|
||||
|
||||
## 内存合并的思路
|
||||
|
||||
### 前合并的情况:
|
||||
|
||||
```
|
||||
(START) -> (内存块A, size=5) -> (内存块B, size=3)
|
||||
|
||||
插入内存块C(size=2),发现C紧邻A,且A在前,则:
|
||||
|
||||
(START) -> (内存块A+C, size=5+2=7) -> (内存块B, size=3)
|
||||
```
|
||||
|
||||
### 后合并的情况:
|
||||
```
|
||||
(START) -> (内存块A, size=5) -> (内存块B, size=3) -> (内存块C, size=2)
|
||||
|
||||
插入内存块D(size=3),发现D紧邻B,且B在后,则:
|
||||
|
||||
(START) -> (内存块A, size=5) -> (内存块D+B, size=3+3=6) -> (内存块C, size=2)
|
||||
```
|
||||
### 不合并的情况:
|
||||
|
||||
```
|
||||
(START) -> (内存块A, size=5) -> (内存块B, size=3) -> (内存块C, size=2)
|
||||
|
||||
插入内存块D(size=1),D在A和B之间且都不相连,则:
|
||||
|
||||
(START) -> (内存块A, size=5) -> (内存块D, size=1) -> (内存块B, size=3) -> (内存块C, size=2)
|
||||
```
|
||||
|
||||
## 创建内存数组
|
||||
|
||||
创建静态数组,用来作为内存管理分配的内存。
|
||||
|
||||
```c
|
||||
/* 定义4K空间 */
|
||||
#define MR_CFG_HEAP_SIZE (4 * 1024)
|
||||
static uint8_t heap_mem[MR_CFG_HEAP_SIZE] = {0};
|
||||
```
|
||||
|
||||
## 创建内存管理结构体
|
||||
|
||||
定义内存块,由下一块内存块指针、内存块大小、内存分配标志位组成。
|
||||
|
||||
- 下一块内存块指针:用于实现链式内存块存储,表示下一个内存块的地址。
|
||||
- 内存块大小:记录该内存块的大小。
|
||||
- 内存分配标志位:使用1比特来表示内存块当前的状态,0表示未分配,1表示已分配。
|
||||
|
||||
```c
|
||||
#define MR_HEAP_BLOCK_FREE (0)
|
||||
#define MR_HEAP_BLOCK_ALLOCATED (1)
|
||||
#define MR_HEAP_BLOCK_MIN_SIZE (sizeof(struct mr_heap_block) << 1)
|
||||
|
||||
static struct mr_heap_block
|
||||
{
|
||||
struct mr_heap_block *next;
|
||||
uint32_t size: 31;
|
||||
uint32_t allocated: 1;
|
||||
} heap_start = {MR_NULL, 0, MR_HEAP_BLOCK_FREE};
|
||||
```
|
||||
|
||||
## 初始化内存管理
|
||||
|
||||
为内存初始化内存块,将整块内存作为单个内存块。
|
||||
|
||||
```c
|
||||
int mr_heap_init(void)
|
||||
{
|
||||
struct mr_heap_block *first_block = (struct mr_heap_block *)&heap_mem;
|
||||
|
||||
/* 初始化内存块(消耗一个 sizeof(struct mr_heap_block)) */
|
||||
first_block->next = MR_NULL;
|
||||
first_block->size = sizeof(heap_mem) - sizeof(struct mr_heap_block);
|
||||
first_block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* 初始化起始内存块,启动内存管理 */
|
||||
heap_start.next = first_block;
|
||||
return MR_EOK;
|
||||
}
|
||||
```
|
||||
|
||||
## 分配内存
|
||||
|
||||
```c
|
||||
void *mr_malloc(size_t size)
|
||||
{
|
||||
struct mr_heap_block *block_prev = &heap_start;
|
||||
struct mr_heap_block *block = block_prev->next;
|
||||
void *memory = MR_NULL;
|
||||
size_t residual = 0;
|
||||
|
||||
/* 检查需要申请的内存过小、内存过大,以及内存管理器中还有无内存 */
|
||||
if ((size == 0) || (size > (UINT32_MAX >> 1) || (block == MR_NULL)))
|
||||
{
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* 字节向上做4对齐 */
|
||||
size = mr_align4_up(size);
|
||||
|
||||
/* 找到符合内存分配大小的内存块 */
|
||||
while (block->size < size)
|
||||
{
|
||||
if (block->next == MR_NULL)
|
||||
{
|
||||
return MR_NULL;
|
||||
}
|
||||
/* 脱离合理的内存块 */
|
||||
block_prev = block;
|
||||
block = block->next;
|
||||
}
|
||||
/* 断开内存块链接 */
|
||||
block_prev->next = block->next;
|
||||
|
||||
/* 生成新的内存块并返回内存 */
|
||||
memory = (void *)((uint8_t *)block) + sizeof(struct mr_heap_block);
|
||||
/* 剩余内存大小*/
|
||||
residual = block->size - size;
|
||||
|
||||
/* 设置被分配的内存块 */
|
||||
block->size = size;
|
||||
block->next = MR_NULL;
|
||||
block->allocated = MR_HEAP_BLOCK_ALLOCATED;
|
||||
|
||||
/* 检测是否够空间生成新的内存块 (MR_HEAP_BLOCK_MIN_SIZE)左移两位等于2倍,需要有大于2个内存块大小,才生成新的内存块 */
|
||||
if (residual > MR_HEAP_BLOCK_MIN_SIZE)
|
||||
{
|
||||
struct mr_heap_block *new_block = (struct mr_heap_block *)(((uint8_t *)memory) + size);
|
||||
|
||||
/* 设置新内存块 */
|
||||
new_block->size = residual - sizeof(struct mr_heap_block);
|
||||
new_block->next = MR_NULL;
|
||||
new_block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* 将内存块插入到内存块链表中 */
|
||||
heap_insert_block(new_block);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
```
|
||||
|
||||
## 释放内存
|
||||
|
||||
```c
|
||||
void mr_free(void *memory)
|
||||
{
|
||||
/* 判断内存是否为有效 */
|
||||
if (memory != MR_NULL)
|
||||
{
|
||||
struct mr_heap_block *block = (struct mr_heap_block *)((uint8_t *)memory - sizeof(struct mr_heap_block));
|
||||
|
||||
/* 检查内存块是否可以释放 */
|
||||
if (block->allocated == MR_HEAP_BLOCK_ALLOCATED && block->size != 0)
|
||||
{
|
||||
block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* 将内存块插入到内存块链表中 */
|
||||
heap_insert_block(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 插入内存块
|
||||
|
||||
```c
|
||||
void heap_insert_block(struct mr_heap_block *block)
|
||||
{
|
||||
struct mr_heap_block *block_prev = &heap_start;
|
||||
|
||||
/* 搜索前一内存块 */
|
||||
while (((block_prev->next != MR_NULL) && ((uint32_t)block_prev->next < (uint32_t)block)))
|
||||
{
|
||||
block_prev = block_prev->next;
|
||||
}
|
||||
|
||||
if (block_prev->next != MR_NULL)
|
||||
{
|
||||
/* 如果前一内存块与需要插入的内存块相连则向前合并 */
|
||||
if ((void *)(((uint8_t *)block_prev) + sizeof(struct mr_heap_block) + block_prev->size) == (void *)block)
|
||||
{
|
||||
block_prev->size += block->size + sizeof(struct mr_heap_block);
|
||||
block = block_prev;
|
||||
}
|
||||
|
||||
/* 如果需要插入的内存块与后一内存块于相连则向后合并 */
|
||||
if ((void *)(((uint8_t *)block) + sizeof(struct mr_heap_block) + block->size) == (void *)block_prev->next)
|
||||
{
|
||||
block->size += block_prev->next->size + sizeof(struct mr_heap_block);
|
||||
block->next = block_prev->next->next;
|
||||
|
||||
/* 判断当前内存块是否插入*/
|
||||
if (block != block_prev)
|
||||
{
|
||||
block_prev->next = block;
|
||||
block = block_prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 若内存块未插入,则插入内存块 */
|
||||
if (block != block_prev)
|
||||
{
|
||||
block->next = block_prev->next;
|
||||
block_prev->next = block;
|
||||
}
|
||||
}
|
||||
```
|
||||
245
document/mem_manager/mem_manager_EN.md
Normal file
245
document/mem_manager/mem_manager_EN.md
Normal file
@@ -0,0 +1,245 @@
|
||||
# Dynamic Memory Management
|
||||
|
||||
[中文](mem_manager.md)
|
||||
|
||||
<!-- TOC -->
|
||||
* [Dynamic Memory Management](#dynamic-memory-management)
|
||||
* [Main Functions:](#main-functions)
|
||||
* [Idea of Memory Merging](#idea-of-memory-merging)
|
||||
* [Front Merging Situation:](#front-merging-situation)
|
||||
* [Back Merging Situation:](#back-merging-situation)
|
||||
* [Non-merging Situation:](#non-merging-situation)
|
||||
* [Create Memory Array](#create-memory-array)
|
||||
* [Create Memory Management Structure](#create-memory-management-structure)
|
||||
* [Memory Management Initialization](#memory-management-initialization)
|
||||
* [Memory Allocation](#memory-allocation)
|
||||
* [Memory Release](#memory-release)
|
||||
* [Insert Memory Block](#insert-memory-block)
|
||||
<!-- TOC -->
|
||||
|
||||
## Main Functions:
|
||||
|
||||
- Dynamic memory block allocation - Select an unallocated memory block according to the application's request to
|
||||
allocate.
|
||||
- Memory block release and recycling - Release it and mark it as unallocated when the block is no longer needed.
|
||||
- Records of allocated and unallocated blocks - Real-time tracking of status information of each block using data
|
||||
structures such as linked lists or arrays.
|
||||
- Memory block merging - After releasing a block, check the status of adjacent blocks. If both are unallocated, merge
|
||||
them into a larger block to reduce fragmentation.
|
||||
|
||||
## Idea of Memory Merging
|
||||
|
||||
### Front Merging Situation:
|
||||
|
||||
```
|
||||
(START) -> (Memory block A, size=5) -> (Memory block B, size=3)
|
||||
|
||||
Insert memory block C(size=2), find C adjacent to A, and A is in front, then:
|
||||
|
||||
(START) -> (Memory block A+C, size=5+2=7) -> (Memory block B, size=3)
|
||||
```
|
||||
|
||||
### Back Merging Situation:
|
||||
|
||||
```
|
||||
(START) -> (Memory block A, size=5) -> (Memory block B, size=3) -> (Memory block C, size=2)
|
||||
|
||||
Insert memory block D(size=3), find D adjacent to B, and B is behind, then:
|
||||
|
||||
(START) -> (Memory block A, size=5) -> (Memory block D+B, size=3+3=6) -> (Memory block C, size=2)
|
||||
```
|
||||
|
||||
### Non-merging Situation:
|
||||
|
||||
```
|
||||
(START) -> (Memory block A, size=5) -> (Memory block B, size=3) -> (Memory block C, size=2)
|
||||
|
||||
Insert memory block D(size=1), D between A and B and not connected, then:
|
||||
|
||||
(START) -> (Memory block A, size=5) -> (Memory block D, size=1) -> (Memory block B, size=3) -> (Memory block C, size=2)
|
||||
```
|
||||
|
||||
## Create Memory Array
|
||||
|
||||
Create a static array to be used as the memory for memory management allocation.
|
||||
|
||||
```c
|
||||
/* Define 4K space */
|
||||
#define MR_CFG_HEAP_SIZE (4 * 1024)
|
||||
static uint8_t heap_mem[MR_CFG_HEAP_SIZE] = {0};
|
||||
```
|
||||
|
||||
## Create Memory Management Structure
|
||||
|
||||
Define memory block, consisting of next memory block pointer, memory block size, memory allocation flag.
|
||||
|
||||
- Next memory block pointer: Used to implement linked memory block storage, indicating the address of the next memory
|
||||
block.
|
||||
- Memory block size: Records the size of this memory block.
|
||||
- Memory allocation flag: Use 1 bit to indicate the current status of the memory block, 0 means unallocated, 1 means
|
||||
allocated.
|
||||
|
||||
```c
|
||||
#define MR_HEAP_BLOCK_FREE (0)
|
||||
#define MR_HEAP_BLOCK_ALLOCATED (1)
|
||||
#define MR_HEAP_BLOCK_MIN_SIZE (sizeof(struct mr_heap_block) << 1)
|
||||
|
||||
static struct mr_heap_block
|
||||
{
|
||||
struct mr_heap_block *next;
|
||||
uint32_t size: 31;
|
||||
uint32_t allocated: 1;
|
||||
} heap_start = {MR_NULL, 0, MR_HEAP_BLOCK_FREE};
|
||||
```
|
||||
|
||||
## Memory Management Initialization
|
||||
|
||||
Initialize the memory block for the entire memory block as a single memory block.
|
||||
|
||||
```c
|
||||
int mr_heap_init(void)
|
||||
{
|
||||
struct mr_heap_block *first_block = (struct mr_heap_block *)&heap_mem;
|
||||
|
||||
/* Initialize memory block (consuming sizeof(struct mr_heap_block)) */
|
||||
first_block->next = MR_NULL;
|
||||
first_block->size = sizeof(heap_mem) - sizeof(struct mr_heap_block);
|
||||
first_block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* Initialize starting memory block, start memory management */
|
||||
heap_start.next = first_block;
|
||||
return MR_EOK;
|
||||
}
|
||||
```
|
||||
|
||||
## Memory Allocation
|
||||
|
||||
```c
|
||||
void *mr_malloc(size_t size)
|
||||
{
|
||||
struct mr_heap_block *block_prev = &heap_start;
|
||||
struct mr_heap_block *block = block_prev->next;
|
||||
void *memory = MR_NULL;
|
||||
size_t residual = 0;
|
||||
|
||||
/* Check if the requested memory size is too small, too large,
|
||||
or if there is no memory available in the memory manager */
|
||||
if ((size == 0) || (size > (UINT32_MAX >> 1) || (block == MR_NULL)))
|
||||
{
|
||||
return MR_NULL;
|
||||
}
|
||||
|
||||
/* Align the size to the next multiple of 4 bytes */
|
||||
size = mr_align4_up(size);
|
||||
|
||||
/* Find a memory block that can accommodate the requested size */
|
||||
while (block->size < size)
|
||||
{
|
||||
if (block->next == MR_NULL)
|
||||
{
|
||||
return MR_NULL;
|
||||
}
|
||||
/* Move to the next memory block */
|
||||
block_prev = block;
|
||||
block = block->next;
|
||||
}
|
||||
/* Disconnect the memory block from the linked list */
|
||||
block_prev->next = block->next;
|
||||
|
||||
/* Create a new memory block and return the memory */
|
||||
memory = (void *)((uint8_t *)block) + sizeof(struct mr_heap_block);
|
||||
/* Calculate the residual memory size */
|
||||
residual = block->size - size;
|
||||
|
||||
/* Set the allocated memory block */
|
||||
block->size = size;
|
||||
block->next = MR_NULL;
|
||||
block->allocated = MR_HEAP_BLOCK_ALLOCATED;
|
||||
|
||||
/* Check if there is enough space to create a new memory block
|
||||
(MR_HEAP_BLOCK_MIN_SIZE shifted left by 2 is equivalent to 2 times),
|
||||
a new memory block is created if there is more than 2 times
|
||||
the size of the memory block */
|
||||
if (residual > MR_HEAP_BLOCK_MIN_SIZE)
|
||||
{
|
||||
struct mr_heap_block *new_block = (struct mr_heap_block *)(((uint8_t *)memory) + size);
|
||||
|
||||
/* Set the new memory block */
|
||||
new_block->size = residual - sizeof(struct mr_heap_block);
|
||||
new_block->next = MR_NULL;
|
||||
new_block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* Insert the new memory block into the linked list of memory blocks */
|
||||
heap_insert_block(new_block);
|
||||
}
|
||||
return memory;
|
||||
}
|
||||
```
|
||||
|
||||
## Memory Release
|
||||
|
||||
```c
|
||||
void mr_free(void *memory)
|
||||
{
|
||||
/* Check if the memory is valid */
|
||||
if (memory != MR_NULL)
|
||||
{
|
||||
struct mr_heap_block *block = (struct mr_heap_block *)((uint8_t *)memory - sizeof(struct mr_heap_block));
|
||||
|
||||
/* Check if the memory block can be released */
|
||||
if (block->allocated == MR_HEAP_BLOCK_ALLOCATED && block->size != 0)
|
||||
{
|
||||
block->allocated = MR_HEAP_BLOCK_FREE;
|
||||
|
||||
/* Insert the memory block into the memory block linked list */
|
||||
heap_insert_block(block);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Insert Memory Block
|
||||
|
||||
```c
|
||||
void heap_insert_block(struct mr_heap_block *block)
|
||||
{
|
||||
struct mr_heap_block *block_prev = &heap_start;
|
||||
|
||||
/* Search for the previous memory block */
|
||||
while (((block_prev->next != MR_NULL) && ((uint32_t)block_prev->next < (uint32_t)block)))
|
||||
{
|
||||
block_prev = block_prev->next;
|
||||
}
|
||||
|
||||
if (block_prev->next != MR_NULL)
|
||||
{
|
||||
/* If the previous memory block is connected to the to-be-inserted memory block, merge forward */
|
||||
if ((void *)(((uint8_t *)block_prev) + sizeof(struct mr_heap_block) + block_prev->size) == (void *)block)
|
||||
{
|
||||
block_prev->size += block->size + sizeof(struct mr_heap_block);
|
||||
block = block_prev;
|
||||
}
|
||||
|
||||
/* If the to-be-inserted memory block is connected to the next memory block, merge backward */
|
||||
if ((void *)(((uint8_t *)block) + sizeof(struct mr_heap_block) + block->size) == (void *)block_prev->next)
|
||||
{
|
||||
block->size += block_prev->next->size + sizeof(struct mr_heap_block);
|
||||
block->next = block_prev->next->next;
|
||||
|
||||
/* Determine if the current memory block is inserted*/
|
||||
if (block != block_prev)
|
||||
{
|
||||
block_prev->next = block;
|
||||
block = block_prev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If the memory block is not inserted, insert the memory block */
|
||||
if (block != block_prev)
|
||||
{
|
||||
block->next = block_prev->next;
|
||||
block_prev->next = block;
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user