slub分配机制
- 如何分配内存块?
- 如何释放内存块?
一个内存块就是一个object。
单个物理页之内分配小内存使用slub分配,页级别的物理内存分配使用伙伴Buddy系统分配。
slub系统如何分配内存块?
从整体上看,
- 当零售商
kmem_cache
初始化后,该kmem_cache
是没有slab的; - 当其他模块需要从该
kmem_cache
中申请一个对象时,kmem_cache
会从伙伴系统获取一段连续的物理页作为一个slab,然后通过kmem_cache
中的cotr函数指针
指向的构造函数构造初始化这个slab,并将其设置为该cpu当前使用的slab; - 当该cpu当前使用的slab使用完后,外部模块在申请对象时,会把这个满的slab移除,再从伙伴系统获取一段连续物理页作为一个新的空闲slab,并设置为该cpu当前使用的slab;
slub系统分配内存块object,需要考虑的情形有:
- 一个slub初始化结束
- 初始化完成后,第一次申请对象
- 运行时申请内存
3.1 当前cpu使用的slab有多余的空闲对象
3.2 当前cpu使用的slab没有多余的空闲对象
3.2.1 当前cpu的部分空slab链表为空
3.2.2 当前cpu的部分空slab链表不为空
一个slub初始化完成时
当一个slub初始化完成时,该slub是没有slab的。
slub刚初始化完成.png
第一次申请内存块object
如果此时是用户第一次申请内存块object,则slub系统会做如下工作:
- 从伙伴系统中获取一段连续的物理页作为一个slab;
- 将该slab分成多个内存块object;
- 从中取出一个内存块object并标记为已占用,返回给用户;
- 将其余内存块object标记为空闲,放在营业厅
kmem_cache_cpu
中保存,即使用kmem_cache_cpu
的freelist
变量来保存下一个空闲object的地址;
slub初始化后第一次申请内存块.png
当前cpu使用的slab有多余的空闲对象
如果此时用户申请内存块object,则slub系统会做如下工作:
直接从这些多余的空闲对象中分配一个出去给用户。
具体地讲,就是直接将kmem_cache_cpu
中保存的一个空闲object返回给用户,并把freelist
指向下一个空闲的object。
当前cpu使用的slab满了
- 当前cpu的部分空slab链表不为空
- 当前cpu的部分空slab链表为空
当前cpu的部分空slab链表不为空
如果此时用户申请内存块时,则slub系统会做如下工作:
- 从营业厅
kmem_cache_cpu
中将当前使用的满slab移除; - 从
kmem_cache_cpu
的部分空slab链表中获取一个部分空的slab,并设置为kmem_cache_cpu
当前使用的slab;
当前cpu使用的slab满但部分空slab链表不为空.png
当前cpu的部分空slab链表为空
如果此时用户申请内存块时,则slub系统会做如下工作:
- 从
kmem_cache_node
的部分空slab链表获取若干个部分空slab; - 将前面得到的若干个部分空slab放入
kmem_cache_cpu
的部分空slab链表中; - 执行情形当前cpu的部分空slab链表不为空;
当前cpu使用的slab和部分空slab链表都满了.png
slub系统如何释放内存?
从整体上看,
- 当那些满slab中有对象释放时,SLUB分配器优先把这些slab放入该cpu对应的部分空slab链表;
- 当一个部分空slab通过释放对象成为了一个空闲slab时,SLUB分配器会视情况而定将此空闲slab释放还是加入到node结点的部分空slab链表中;
slub系统释放内存块需要考虑的情形有:
- 部分空的slab释放其中一个已占用的内存块object后仍是部分空slab;
- 满slab释放一个内存块object后,变成了部分空slab
- 部分空slab释放一个内存块object后,变成了空闲slab
部分空的slab释放内存块object后仍是部分空slab
直接释放该内存块即可。
满slab释放一个内存块object后变成了部分空slab
将该部分空slab放入kmem_cache_cpu
的部分空链表中。
部分空slab释放一个内存块object后,变成了空闲slab
slub系统会做有如下工作:
- 检查
kmem_cache_node
的部分空链表中slab缓冲区的个数; - 如果其中slab数量小于
kmem_cache
中的min_partial
,则将该空闲slab放入kmem_cache_node
的部分空链表中; -
否则释放此空闲slab,将其占用页框返回伙伴系统中;
部分空slab释放后变空闲.png
类比机制
从整体上看:slub系统相当于零售商,先向伙伴系统批发内存,然后再零售出去。
具体地看:
- 一个
kmem_cache
结构体相当于一个特定大小内存的零售商; - 整个slub系统共有12个这样的零售商
kmem_cache
,每个零售商kmem_cache
只零售特定大小的内存; - 每个零售商
kmem_cache
有两个部门,一个营业厅kmem_cache_cpu
,一个仓库kmem_cache_node
; - 营业厅
kmem_cache_cpu
里只保留一个slab,且只有在营业厅kmem_cache_cpu
中没有空闲内存时才从仓库中换出其他的slab; - 一个slab就是零售商
kmem_cache
批发的连续的整页内存;零售商将这些整页的内存分成许多小内存,然后分别零售出去;一个slab可能包含多个连续的内存页;slab的大小跟零售商有关;
网友评论