所属专栏: 深入浅出内存管理
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rikeyone/article/details/85490149
存在的意义
页分配器只能按页为单位进行内存分配,但对于不足一页的申请,如果依然按一页来分配,就会造成内存的浪费,slab分配器就是为了完成小内存的分配和管理的。slab分配器建立在页分配器之上,它最终也是从页分配器申请得到整页内存,但是它对页内内存进行了更细化的管理,这一套机制有助于缓解内碎片问题。
设计思想
slab分配器把内存区看作对象来进行管理,并对外提供申请和释放的接口。它的核心是维护一个slab高速缓存,当外部请求对象时,slab会创建并初始化对象,而在释放时,并不会立即释放内存,而是放入slab高速缓存中进行维护,由此避免后续请求导致的反复创建和初始化。
接口
kmem_cache是slab管理内存的核心数据结构,slab分配器把对象分组放入kmem_cache中进行管理,对外接口:
kmem_cache_create
创建kmem_cache。
kmem_cache_destroy
销毁我们创建的kmem_cache。
kmem_cache_alloc
从创建的kmem_cache中申请对象。
kmem_cache_free
释放对象到kmem_cache。
实现细节
slab分配器的实现包含了per cpu 对象高速缓存,共享高速缓存,slab这三层结构部分。
当进行内存分配时:
1.尝试从per cpu对象高速缓存中获取
2.如果当前CPU没有空闲的对象高速缓存,那么会判断共享高速缓存中是否由空闲对象,提取一部分放入本地高速缓存
3.如果共享高速缓存中没有空闲对象,那么最后当前的slab链表中查找是否和合适的空闲slab,并把对象放到本地高速缓存中
4.如果slab中也已经没有空闲对象了,那么此时就要掉要页分配器分配内存,创建新的slab并加入到slab管理的链表中,并从1开始重新进行分配。
per cpu对象高速缓存
类似于伙伴系统拥有一个per cpu页高速缓存,slab同样也由一个per cpu的高速缓存,这样能够让一个对象尽量运行在同一个CPU上,从而提升cache命中概率,提高性能,另一个好处是减少了CPU间的同步开销。这里缓存的是slab中对象的指针.
共享高速缓存
顾名思义,这个缓存是给CPU使用的,当per cpu本地缓存没有空闲时,会从这个共享缓存中获取。需要注意的是,这里缓存的是slab中对象的指针.
slab
slab是由一个或者多个页组成,其中包含一个或者多个对象,这些对象可以是已经分配的,也可能是空闲对象。一个slab有多大,是跟对象大小有关的,另外还需要保证它是按页分配的。