sentence sematic mofication from mm.md
This commit is contained in:
parent
5602df5d48
commit
0e68e78b25
|
@ -18,7 +18,7 @@
|
|||
<span id="intro"></span>
|
||||
|
||||
## 前言
|
||||
XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,通过静态内存管理和动态内存管理相结合,保证分配和释放内存的实时性,提高内存的使用率,有效地规避了内存碎片问题,同时增加了内存检索的速度。
|
||||
XiUOS 操作系统提供了独特的内存管理分配算法进行内存管理,通过静态内存管理和动态内存管理相结合,保证分配和释放内存的实时性,提高内存的使用率,有效地规避了内存碎片问题,同时增加了内存检索的速度。
|
||||
|
||||
<span id="mm_heap"></span>
|
||||
|
||||
|
@ -31,7 +31,7 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
<span id="mm_heap_static_split"></span>
|
||||
|
||||
#### 静态内存划分
|
||||
静态内存包含2个链表。其中,每个链表都具有block_size静态内存块大小、total_count静态内存块的总个数、free_count空闲内存块的总个数和free_list空闲链表这四个属性。
|
||||
静态内存包含2个链表,其中,每个链表都具有 block_size、total_count、free_count和free_list 这四个属性。
|
||||
* block_size 记录了当前链表中每个静态内存块的大小
|
||||
* total_count 记录了系统初始化之后分配给该链表中静态内存块的总个数
|
||||
* free_count 记录了该链表中还可以分配给用户静态内存块的个数
|
||||
|
@ -47,24 +47,19 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
|
||||
#### 静态内存分配
|
||||
在用户发起内存分配请求时,若用户请求分配的内存空间大小小于等于预设的静态内存阈值,且所述静态内存区域有相应空闲的内存块,则从静态内存区域分配相应大小的内存空间。
|
||||
</br></br>
|
||||
在用户发起内存释放请求时,所述分配释放请求解析根据用户提供的内存地址决定后续的操作:
|
||||
|
||||
> 如果所述内存地址是不合法的,则直接返回结果给用户。
|
||||
> 如果所述内存地址是合法地址,分配释放请求解析模块解析所述内存地址所属内存区域,所述内存地址在静态内存区域,则内存分配任务由静态内存管理模块负责;所述内存地址在动态内存区域,则内存分配任务由动态内存管理模块负责。
|
||||
|
||||
从静态内存区域分配静态内存块的过程,包括三种情况。</br>
|
||||
+ 当用户请求分配内存大小小于等于32字节,那么分配释放请求解析模块解析该内存大小由静态内存管理模块负责。系统获取静态链表头1,从静态链表头1中获取一个静态内存块返回给用户;</br>
|
||||
+ 当用户请求分配内存大小为33~64字节,那么分配释放请求解析模块解析该内存大小由静态内存管理模块负责。系统获取静态链表头2,从静态链表头2中获取一个静态内存块返回给用户;</br>
|
||||
+ 若所获得的静态链表头是一个空的链表,即没有空闲的静态内存块可用,那么通知分配释放请求解析模块在静态内存区域中内存分配失败。
|
||||
从静态内存区域分配静态内存块的过程,包括三种情况。
|
||||
+ 当用户请求分配内存大小小于等于32字节,那么分系统获取静态链表头1,从静态链表头1中获取一个静态内存块返回给用户;
|
||||
+ 当用户请求分配内存大小为33~64字节,那么系统获取静态链表头2,从静态链表头2中获取一个静态内存块返回给用户;
|
||||
+ 若所获得的静态链表头是一个空的链表,即没有空闲的静态内存块可用,那么静态内存分配失败。
|
||||
|
||||
<span id="mm_heap_static_free"></span>
|
||||
|
||||
#### 静态内存释放
|
||||
当用户请求释放内存,所述内存用ptr表示,释放操作包括三种情况。</br>
|
||||
+ 所述ptr内存地址是不合法的,则直接返回释放操作。</br>
|
||||
+ 所述ptr指向的静态内存块属于静态链表头1管理,则将所述ptr指向的静态内存块放置到链表头1的头部;</br>
|
||||
+ 若所述ptr指向的静态内存块属于链表头2管理,则将所述ptr指向的静态内存块放置到链表头2的头部。
|
||||
当用户请求释放内存,释放操作包括三种情况。
|
||||
+ 要释放的内存地址是不合法的,则直接返回释放操作;
|
||||
+ 要释放的内存地址属于静态链表头1区域,则将内存块放置到链表头1的头部;
|
||||
+ 要释放的内存地址属于链表头2区域,则将内存块放置到链表头2的头部。
|
||||
|
||||
<span id="mm_heap_dynamic"></span>
|
||||
|
||||
|
@ -73,7 +68,7 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
<span id="mm_heap_dynamic_split"></span>
|
||||
|
||||
#### 动态内存划分
|
||||
静态内存划分后,剩下的内存区域作为动态内存分配给动态内存区域。动态内存区域管理用到了三种重要的数据结构,分别是已分配动态内存段、空闲动态内存段和动态内存管理数据结构。下图显示了已分配动态内存段和空闲动态内存段这两种数据结构。其中,已分配动态内存包括元数据信息和用户的数据段(用户数据),元数据信息中的size属性记录了该动态内存段的内存大小,prev_size属性则记录了该动态内存段前一个相邻动态内存段的内存大小,从而可以获取前一个相邻动态内存段。用户数据则是分配给用户使用的内存空间。空闲动态内存段的元数据信息具有size、prev_size、prev和next这四个属性,其中,size和prev_size属性与已分配动态内存段的对应属性表示的意义相同,prev属性记录了前一个空闲动态内存段,最后一个next属性则记录了下一个空闲动态内存段。
|
||||
静态内存划分后,剩下的内存区域作为动态内存分配给动态内存区域。动态内存区域管理用到了三种重要的数据结构,分别是已分配动态内存段、空闲动态内存段和动态内存管理数据结构。下图显示了已分配动态内存段和空闲动态内存段这两种数据结构。其中,已分配动态内存包括元数据信息和用户的数据段(用户数据),元数据信息中的 size 属性记录了该动态内存段的内存大小,prev_size 属性则记录了该动态内存段前一个相邻动态内存段的内存大小,从而可以获取前一个相邻动态内存段。用户数据则是分配给用户使用的内存空间。空闲动态内存段的元数据信息具有 size、prev_size、prev 和 next 这四个属性,其中,size 和 prev_size 属性与已分配动态内存段的对应属性表示的意义相同,prev 属性记录了前一个空闲动态内存段,最后一个 next 属性则记录了下一个空闲动态内存段。
|
||||
</br></br>
|
||||
<div style="display: flex;justify-content: center;align-items: center;">
|
||||
<img src="./imagesrc/fig2.png" width =90%/>
|
||||
|
@ -85,8 +80,8 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
<img src="./imagesrc/fig3.png" width =80%/>
|
||||
</div>
|
||||
</br></br>
|
||||
动态内存管理数据结构是动态内存区域管理中的核心数据结构,用于组织所有的空闲动态内存段。所述动态内存管理数据结构具有total_size、dynamic_start、dynamic_end和freeLists这四个属性,其中,total_size属性用于记录动态内存区域的大小,dynamic_start属性用于记录起始地址处已分配动态内存段,dynamic_end属性用于记录结尾处已分配动态内存段,freeLists属性是一个多级链表,每一级链表记录了内存大小在指定范围的空闲动态内存段。根据空闲内存段的大小,系统判断空闲内存段所属动态链表,然后将空闲内存段插入不同的空闲链表中。</br></br>
|
||||
系统配置空闲链表的个数为10。当动态内存段大小在1-31字节之间,则插入到空闲链表freeList1中,当动态内存段大小在32-63字节之间时,则插入到空闲链表freeList2中,需要特别说明的是,当动态内存段大小大于或者等于8192字节时,都插入到空闲链表freeList10中。如下表所示:
|
||||
动态内存管理数据结构是动态内存区域管理中的核心数据结构,用于组织所有的空闲动态内存段。所述动态内存管理数据结构具有 total_size、dynamic_start、dynamic_end和freeLists 这四个属性,其中,total_size 属性用于记录动态内存区域的大小,dynamic_start 属性用于记录起始地址处已分配动态内存段,dynamic_end 属性用于记录结尾处已分配动态内存段,freeLists 属性是一个多级链表,每一级链表记录了内存大小在指定范围的空闲动态内存段。根据空闲内存段的大小,系统判断空闲内存段所属动态链表,然后将空闲内存段插入不同的空闲链表中。</br></br>
|
||||
系统可配置空闲链表的个数为10。当动态内存段大小在1-31字节之间,则插入到空闲链表freeList1中,当动态内存段大小在32-63字节之间时,则插入到空闲链表freeList2中,需要特别说明的是,当动态内存段大小大于或者等于8192字节时,都插入到空闲链表freeList10中。如下表所示:
|
||||
|
||||
<div>
|
||||
<table style="margin-left: auto; margin-right: auto; table-layout: fixed;" width = 500 >
|
||||
|
@ -144,17 +139,17 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
<span id="mm_heap_dynamic_alloc"></span>
|
||||
|
||||
#### 动态内存分配
|
||||
系统根据要分配或者要释放的内存段大小计算要操作的内存段链表头,当内存段大小为1 ~ 31字节,那么内存计算单元计算之后将获取空闲动态链表头freeList1,当内存段大小为32 ~63字节,那么内存计算单元计算之后将获取动态链表头freeList2。以此类推。</br></br>
|
||||
当用户请求从动态内存段申请内存时,动态内存管理模块只能有以下几种分配情况:</br>
|
||||
+ 用户请求分配30个字节,freeList1链表中有一个32字节内存大小可以满足用户的需求,之后进行内存块的分割操作,32可以分配为30字节 + 2字节,但是2字节小于系统要求的8字节对齐大小,因此将32字节内存返回给用户;</br>
|
||||
+ 用户请求分配45个字节,并且系统已经知道静态内存区域无法分配。内存计算单元计算45字节对应的空闲动态链表,获取freeList2,freeList2链表中有一个56字节内存大小可以满足用户的需求,之后进行内存块的分割操作,56可以分配为45字节 + 11字节,11字节小于系统要求的8字节对齐大小,因此,除了返回45字节动态内存给用户,还要执行11字节的内存释放操作;</br>
|
||||
+ 用户请求分配8000个字节。内存计算单元计算8000字节对应的空闲动态链表,获取freeList9,freeList9链表中没有空闲动态内存段,没有找到可分配的动态内存段并且freeList9不是最后一级链表,更新链表头到freeList10,freeList10链表中动态内存段可以满足用户的需求,之后进行内存块的分割操作,9000可以分配为8192字节 + 808字节,808字节大于系统要求的8字节对齐大小,因此,除了返回8192动态内存给用户,还要执行808字节的释放操作;</br>
|
||||
+ 用户请求分配6000000个字节。内存计算单元计算6000000字节对应的空闲动态链表,获取freeList10,freeList10链表中没有空闲动态内存段,没有找到可分配的动态内存段并且freeList10是最后一级链表,内存分配操作失败,结束内存分配操作。</br>
|
||||
系统根据要分配或者要释放的内存段大小计算要操作的内存段链表头,当内存段大小为1 ~ 31字节,那么计算之后将获取空闲动态链表头freeList1,当内存段大小为32 ~ 63字节,那么计算之后将获取动态链表头freeList2,依次类推。
|
||||
当用户请求从动态内存段申请内存时,有以下几种分配情况:
|
||||
+ 用户请求分配n个字节(对齐后的字节),freeListK 链表中有一个m字节内存大小可以满足用户的需求,之后进行内存块的分割操作,分成n字节和(n-m)字节,其中 n-m 小于 8字节,因此将m字节内存返回给用户;
|
||||
+ 用户请求分配n个字节(对齐后的字节),freeListK 链表中有一个m字节内存大小可以满足用户的需求,之后进行内存块的分割操作,分成n字节和(n-m)字节,其中 n-m 大于或等于 8字节,因此将n字节内存返回给用户并且将n-m个字节重新插入动态内存管理结构;
|
||||
+ 用户请求分配n个字节(对齐后的字节),freeListK 链表中没有空闲内存大小可以满足用户的需求,并且freeListK+1级链表存在,则从freeListK+1链表中分配内存;
|
||||
+ 用户请求分配n个字节(对齐后的字节),freeListK 链表中没有空闲内存大小可以满足用户的需求,并且freeListK+1级链表不存在,则内存分配失败。
|
||||
|
||||
<span id="mm_heap_dynamic_free"></span>
|
||||
|
||||
#### 动态内存释放
|
||||
当用户请求释放内存,所述内存用ptr表示。分配释放请求解析模块解析判断ptr所述区域为动态内存区域,则将释放ptr所指向的内存区域到动态内存段中。
|
||||
当用户请求释放内存,系统释放内存区域到对应的动态内存段中。
|
||||
|
||||
<div style="display: flex;justify-content: center;align-items: center;">
|
||||
<img src="./imagesrc/fig9.png" width =95%/>
|
||||
|
@ -168,8 +163,7 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
<span id="mempool"></span>
|
||||
|
||||
## 内存池
|
||||
内存堆管理器可以分配任意大小的内存块,非常灵活和方便。但其也存在明显的缺点:一是分配效率不高,在每次分配时,都要空闲内存块查找;二是容易产生内存碎片。为了提高内存分配的效率,并且避免内存碎片,XiUOS提供了另外一种内存管理方法:内存池。
|
||||
</br></br>
|
||||
内存堆管理器可以分配任意大小的内存块,非常灵活和方便。但其也存在明显的缺点:一是分配效率不高,在每次分配时,都要空闲内存块查找;二是容易产生内存碎片。为了提高内存分配的效率,并且避免内存碎片,XiUOS提供了另外一种内存管理方法,内存池。
|
||||
内存池在创建时先向系统预先申请分配一定数量、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时,就从内存池中分出一部分内存块,若内存块不够再继续申请新的内存。
|
||||
|
||||
<span id="func_api"></span>
|
||||
|
@ -180,7 +174,7 @@ XiUOS操作系统提供了独特的内存管理分配算法进行内存管理,
|
|||
|
||||
#### 内存初始化
|
||||
```C
|
||||
void xs_SystemHeapInit(void *start_phy_address, void *end_phy_address)
|
||||
void xs_SystemHeapInit(void *start_phy_address, void *end_phy_address);
|
||||
```
|
||||
这个函数用来初始化静态和动态内存。
|
||||
|
||||
|
@ -194,9 +188,9 @@ void xs_SystemHeapInit(void *start_phy_address, void *end_phy_address)
|
|||
|
||||
#### 分配和释放内存
|
||||
```C
|
||||
void *xs_malloc(xs_size_t size)
|
||||
void *xs_malloc(xs_size_t size);
|
||||
```
|
||||
这个函数用来分配一块合适大小的内存,如果分配成功,则返回分配内存的首地址;如果分配失败,则返回NULL。
|
||||
这个函数用来分配一块合适大小的内存,如果分配成功,则返回分配内存的首地址;否则返回NULL。
|
||||
|
||||
|
||||
| 参数 | 描述 |
|
||||
|
@ -205,19 +199,19 @@ void *xs_malloc(xs_size_t size)
|
|||
</br>
|
||||
|
||||
```C
|
||||
void *xs_realloc(void *pointer, xs_size_t size)
|
||||
void *xs_realloc(void *pointer, xs_size_t size);
|
||||
```
|
||||
这个函数用来重新分配一块内存,将原内存块中的数据保存到新的内存中去,并将原内存块释放。如果分配成功,则返回分配内存的首地址;如果分配失败,则返回NULL。
|
||||
这个函数用来重新分配一块内存,将原内存块中的数据保存到新的内存中去,并将原内存块释放。如果分配成功,则返回分配内存的首地址;否则返回NULL。
|
||||
|
||||
|
||||
| 参数 | 描述 |
|
||||
| :------ | :------ |
|
||||
| pointer | 原内存块的指针 |
|
||||
| size | 需要被分配的内存大小 |
|
||||
| size | 需要重新分配的内存大小 |
|
||||
</br>
|
||||
|
||||
```C
|
||||
void *xs_calloc(xs_size_t count, xs_size_t size)
|
||||
void *xs_calloc(xs_size_t count, xs_size_t size);
|
||||
```
|
||||
这个函数会分配多个内存块并将内存块中的数据初始化为0。
|
||||
|
||||
|
@ -230,19 +224,19 @@ void *xs_calloc(xs_size_t count, xs_size_t size)
|
|||
|
||||
|
||||
```C
|
||||
void xs_free(void *pointer)
|
||||
void xs_free(void *pointer);
|
||||
```
|
||||
这个函数用来释放一个内存块
|
||||
这个函数用来释放内存。
|
||||
|
||||
|
||||
| 参数 | 描述 |
|
||||
| :------ | :------ |
|
||||
| pointer | 指向需要被释放的内存块的指针 |
|
||||
| pointer | 指向需要被释放的内存 |
|
||||
</br>
|
||||
|
||||
#### 内存钩子函数
|
||||
```C
|
||||
void xs_MallocSetHook(void (*MallocHook)(void *pointer, xs_size_t size))
|
||||
void xs_MallocSetHook(void (*MallocHook)(void *pointer, xs_size_t size));
|
||||
```
|
||||
这个函数设置了一个 MallocHook 函数,MallocHook 函数会在动态内存分配之前调用。
|
||||
|
||||
|
@ -253,7 +247,7 @@ void xs_MallocSetHook(void (*MallocHook)(void *pointer, xs_size_t size))
|
|||
</br>
|
||||
|
||||
```C
|
||||
void xs_FreeSetHook(void (*FreeHook)(void *pointer))
|
||||
void xs_FreeSetHook(void (*FreeHook)(void *pointer));
|
||||
```
|
||||
这个函数设置了一个FreeHook 函数, FreeHook 函数会在内存块被释放回动态内存区时调用。
|
||||
|
||||
|
@ -295,9 +289,9 @@ void list_buddy(void)
|
|||
|
||||
#### 创建内存池
|
||||
```C
|
||||
xs_gm_t xs_CreateMemGather(const char *gm_name, xs_size_t block_number, xs_size_t one_block_size)
|
||||
xs_gm_t xs_CreateMemGather(const char *gm_name, xs_size_t block_number, xs_size_t one_block_size);
|
||||
```
|
||||
创建一个内存池。如果创建成功,返回第一个内存块的地址,否则返回XS_NULL(0)。
|
||||
创建一个内存池。如果创建成功,返回第一个内存块的地址,否则返回XS_NULL。
|
||||
|
||||
| 参数 | 描述 |
|
||||
| :------ | :------ |
|
||||
|
@ -307,7 +301,7 @@ xs_gm_t xs_CreateMemGather(const char *gm_name, xs_size_t block_number, xs_siz
|
|||
</br>
|
||||
|
||||
```C
|
||||
xs_err_t xs_InitMemGather(struct xs_MemGather *gm_handler, const char *gm_name, void *begin_address, xs_size_t gm_size, xs_size_t one_block_size)
|
||||
xs_err_t xs_InitMemGather(struct xs_MemGather *gm_handler, const char *gm_name, void *begin_address, xs_size_t gm_size, xs_size_t one_block_size);
|
||||
```
|
||||
初始化内存池,用于静态内存管理模式。
|
||||
|
||||
|
@ -322,30 +316,30 @@ xs_err_t xs_InitMemGather(struct xs_MemGather *gm_handler, const char *gm_name,
|
|||
|
||||
#### 删除内存池
|
||||
```C
|
||||
xs_err_t xs_DeleteMemGather(xs_gm_t gm_handler)
|
||||
xs_err_t xs_DeleteMemGather(xs_gm_t gm_handler);
|
||||
```
|
||||
删除由xs_CreateMemGather创建的内存池,返回0。
|
||||
删除由xs_CreateMemGather创建的内存池。
|
||||
|
||||
| 参数 | 描述 |
|
||||
| :------ | :------ |
|
||||
| gm_handler | 需要被删除的内存池地址 |
|
||||
| gm_handler | 需要被删除的内存池 |
|
||||
|
||||
</br>
|
||||
|
||||
```C
|
||||
xs_err_t xs_RemoveMemGather(struct xs_MemGather *gm_handler)
|
||||
xs_err_t xs_RemoveMemGather(struct xs_MemGather *gm_handler);
|
||||
```
|
||||
删除由xs_MemGatherInit创建的内存池,返回0。
|
||||
删除由xs_MemGatherInit创建的内存池。
|
||||
|
||||
| 参数 | 描述 |
|
||||
| :------ | :------ |
|
||||
| gm_handler | 需要被删除的内存池地址 |
|
||||
| gm_handler | 需要被移除的内存池 |
|
||||
|
||||
</br>
|
||||
|
||||
#### 分配内存块
|
||||
```C
|
||||
void *xs_AllocBlockMemGather(xs_gm_t gm_handler, xs_int32 wait_time)
|
||||
void *xs_AllocBlockMemGather(xs_gm_t gm_handler, xs_int32 wait_time);
|
||||
```
|
||||
该函数将从指定的内存池中分配一个内存块。如果内存池中有可用的内存块,则从内存池的空闲块链表上取下一个内存块,将空闲内存块数目减1并返回这个内存块;如果内存池中已经没有空闲内存块,则判断超时时间设置:若超时时间设置为零,则立刻返回空内存块;如果等待时间大于零,则把当前线程挂起在该内存池对象上,直到内存池中有可用的自由内存块,或等待时间到达。
|
||||
|
||||
|
@ -359,7 +353,7 @@ void *xs_AllocBlockMemGather(xs_gm_t gm_handler, xs_int32 wait_time)
|
|||
|
||||
#### 释放内存块
|
||||
```C
|
||||
void xs_FreeBlockMemGather(void *data_block)
|
||||
void xs_FreeBlockMemGather(void *data_block);
|
||||
```
|
||||
这个函数用于释放指定的内存块,然后增加内存池对象的可用内存块数目,并把该被释放的内存块加入空闲内存块链表上。接着判断该内存池对象上是否有挂起的线程,如果有则唤醒挂起线程链表上的首线程。
|
||||
|
||||
|
@ -371,7 +365,7 @@ void xs_FreeBlockMemGather(void *data_block)
|
|||
|
||||
#### 内存池钩子函数
|
||||
```C
|
||||
void xs_GmSetAllocHook(void (*gm_allocation_hook)(struct xs_MemGather *gm, void *date_ptr))
|
||||
void xs_GmSetAllocHook(void (*gm_allocation_hook)(struct xs_MemGather *gm, void *date_ptr));
|
||||
```
|
||||
该钩子函数会在内存池分配之前调用。
|
||||
|
||||
|
@ -382,7 +376,7 @@ void xs_GmSetAllocHook(void (*gm_allocation_hook)(struct xs_MemGather *gm, void
|
|||
</br>
|
||||
|
||||
```C
|
||||
void xs_GmSetFreeHook(void (*gm_release_hook)(struct xs_MemGather *gm, void *date_ptr))
|
||||
void xs_GmSetFreeHook(void (*gm_release_hook)(struct xs_MemGather *gm, void *date_ptr));
|
||||
```
|
||||
该钩子函数会在内存池被删除后调用。
|
||||
|
||||
|
|
Loading…
Reference in New Issue