09 管理内存对象

建立内存页面管理器:既可以分配单个页面,也可以分配多个连续的页面,还能指定在特殊内存地址区域中分配页面;但是这种分配至少是一个页面4KB大小,无法分配一个小于单页大小的 内存;

malloc 函数启发:

  内存对象:

设计:页基础上进行细分,分成32字节、64、128、256、512、1024、2048、4096字节,都是Cache行大小的倍数,这些小块内存为 内存对象;

实现思路:把一个或多个内存页面分配出来,作为一个内存对象的容器,在这个容器中容纳相同的内存对象,即同等大小的内存块;

 1、表示内存对象:

结构体 freobjh_t 表示一个对象,包含一个链表、对象状态、对象的开始地址,链表的作用就是为了找到该对象;

2、内存对象容器:

结构体 kmsob_t  放置内存对象的容器,kmbext_t 用于表示内存对象容器的扩展内存,msomdc_t 用于管理内存对象容器占用的内存,msclst_t 用于管理内存对象容器占用的内存页面所对应的msadsc_t 结构;

3、初始化:

管理 kmsob_t 结构的数据结构,用于挂载不同大小的内存容器,koblst_t 结构体用于挂载kmsob_t 结构,kmsobmgrhed_t 结构体用来管理koblst_t 结构;

初始化kmsob的 init_kmsob 函数调用初始化kmsobmgrhed_t 的 kmsobmgrhed_t_init 函数,其中循环初始化koblst_t 结构体数组;

 kmsobmgrhed_t 结构的实例变量放在之前的memmgrob_t 结构中;

内存管理初始化 init_memmgr 函数中调用 了init_kmsob 函数,对管理内存对象容器的结构进行了初始化;

  分配内存对象:

只是初始化了kmsobmgrhed_t 结构,却没有初始化 kmsob_t 结构;

分配内存对象的接口

void *kmsob_new(size_t msz),分配接口只有一个参数:对象大小;其中调用了核心函数 kmsob_new_core 函数;具体细节如下:

1、查找内存对象容器:

要分配内存对象,就要根据要分配的内存对象大小找到内存对象容器;根据kmsob_t结构挂载在kmsobmgrhed_t结构中的ks_msoblst数组中,因此遍历数组;

onmsz_retn_koblst 函数返回ks_msoblst数组元素的指针,表示先根据内存对象大小找到挂载 kmsob_t 结构体对应的 koblst_t 结构;

onkoblst_retn_newkmsob 函数查询其中的内存对象容器并返回;

2、建立内存对象容器:

上述中第一次分配时肯定没有kmsob_t 结构,会返回null;所以要先建立一个kmsob_t 结构,即建立内存对象容器;

_create_kmsob函数实现,根据分配内存对象大小建立一个内存对象容器;具体先是找到物理内存页面管理器中申请一块连续的内存页面;然后再其中的开始部分建立kmsob_t 结构的实例变量,又在kmsob_t 结构的后面建立freobjh_t 结构数组,并把这个freobjh_t 结构挂载到kmsob_t 结构中的so_frelst 中,最后把kmsob_t 结构,挂载到 kmsobmgrhed_t 结构对应的 koblst_t 结构中;

_create_init_kmsob 函数初始化内存对象容器;

3、扩容内存对象容器:

当内存对象容器没有空余的内存空间产生内存对象,这就要为内存对象容器扩展内存空间了;分配另一块连续的内存空间作为空闲的内存对象,并且把这块内存空间加到内存对象容器中统一管理;

kmsob_extn_pages 函数实现扩展内存页面:首先找物理内存页面管理器分配2或者4个连续的页面;把物理内存页面数对应的kmsob_t 的msomdc_t 结构中的 msclst_t 的结构中,并把对应的msadsc_t 结构加入到kmsob_t 结构中;接着初始化kmbext_t 数据结构,设置内存对象的开始地址为kmbext_t 结构之后,结束地址为扩展内存页面的结束地址;在内存空间中建立内存对象;

4、分配内存对象:

有了内存对象容器,就可以分配内存对象;

kmsob_new_onkmsob 函数:先检查是否有空闲的内存对象,没有就进行扩容操作,接着调用分配核心函数;

kmsob_new_opkmsob 核心函数:从空闲的内存对象链表头中取出第一个内存对象,返回它的首地址;

  释放内存对象容器:

实现:根据释放的内存对象的地址和大小,找到对应的内存对象容器,然后把该内存对象加入到对应的内存对象容器的空闲链表中,最后看看要不要释放内存对象容器占用的物理内存页面;

释放内存对象的接口:

kmsob_delete 函数检查参数通过之后,就调用释核心函数 kmsob_delete_core 函数,根据释放内存对象大小,找到挂载其 kmsob_t 结构的koblst_t 结构;接着执行以下操作;

1、查找内存对象容器:

找到要释放内存对象所属的内存对象容器,释放时查找和分配时的查找不一样,要检查内存对象是不是属于该内存对象容器;

onkoblst_retn_delkmsob 函数:查找释放对象所属的kmsob_t 结构,调用核心函数,

scan_delkmsob_isok 核心函数:检查释放的内存对象是不是在kmsob_t 结构中,检查kmsob_t 结构的自身内存区域和扩展内存区域,比较释放的内存对象的地址是不是落在它们的内存空间中,其大小是否合乎要求;

2、释放内存对象:

找到释放内存对象的kmsob_t 这样就可以释放内存对象了;

kmsob_delete_onkmsob 函数:调用 kmsob_del_opkmsob 核心函数;

kmsob_del_opkmsob 函数:把要释放的内存空间重新初始化,变成一个freobjh_t 结构的实例变量,最后把这个freobjh_t 结构加入到kmsob_t 结构的空闲链表中,

3、销毁内存对象容器

若释放了所有的内存对象,那么这个内存对象容器就为空,下一次请求同样大小的内存对象,那这个容器就能复用;但是若请求不同大小的内存对象,那么空的容器会越来越多,占内存,因此要把空的内存对象容器销毁;

destroy_kmsob 函数:检查一下内存对象容器是不是空闲的;若空闲的,就调用核心函数;

_destroy_kmsob_core 核心函数:释放内存对象扩展空间的物理内存页面,释放内存对象容器本身占用的物理内存页面;顺序不能颠倒;遍历so_mc.mc_kmobinlst中的msadsc_t 结构,msadsc_t 脱链,释放对应的物理内存页面;

命名缩写参考:

bafhlst=block alloc free head list
freobjh=free object head
kmbext=kernel memory block extend
kmsobmgrhed=kernel memory space object manager head
onmsz=on memory size 
kmsob_new_opkmsob=..._Operation

 

posted @ 2023-04-26 22:17  QianFa01  阅读(61)  评论(0)    收藏  举报