1. Abstract
.
2. Introduction
3. 过程分析
3.1 过程介绍
SLUB 的系统其实和 SLAB 的系统很相似,但是做了一些简化:
1. 首先, SLUB 没有再考虑着色的问题了;既申请的页面在开始区域没有着色区,在结束的区域也没有着色补偿;
2. SLUB 不再有单独维护空闲对象列表的对象链表区了,在 SLAB 区域里面有一个单独这样的区域,在 slab 结构后面,对象区域前面;而 SLUB 里面空闲对象链表是通过在每个对象后面留下一个指针的空间来实现的;
3. SLUB 没有 OFF SLAB 或 ON SLAB 的说法,对于 SLAB 而言,大对象,即大于 1/8 个 Page 的对象,是 OFF SLAB 的,对于 OFF SLAB 对象而言, kmem_cache 的 slabp_cache 成员指向通用大小的 kmem_cache( 即 kmalloc 所使用的 kmem_cache) , slab 结构都是在此 kmem_cache 中分配的;而 SLUB 就不管了,只要是大于 1/2 个 Page 的,直接就申请 Page 了,否则都是在对象区域申请的;
4. SLAB 里每次申请一个新的 SLAB 都要产生一个新的 slab 数据结构,如果是 ON SLAB 的,则该数据结构就存在于申请的内存页里,而 SLUB 就不会了,每次申请一个新的 SLAB( 一组页 ) ,都是通过其首页的 freelist, slab, lru 等成员进行管理的,没有其它数据结构,比如,如果新的 SLAB 为当前的 SLAB ,则 kmem_cache-> cpu_slab-> page 就等于其 SLAB 页组的一个页的地址;如果是 Partial 的 SLAB ,则通过 SLAB 页组的一个页的 lru 成员,链接到 kmem_cache->local_node-> partial 成员上。而 SLAB 页组中除了首页之外的其它页,都通过其 first_page 成员,指向首页,首页的 slab 成员,指向其所属的 kmem_cache 。
3.2 代码分析总体介绍
这里先做一些说明, kmem_cache-> cpu_slab-> page 成员,指向当前的 kmem_cache-> cpu_slab->freelist 成员所在的 page ,所以当一个对象释放的时候,如果释放的对象所在的 slab 的首页和 kmem_cache-> cpu_slab-> page 相等的话,就说明这个对象可以直接放到 kmem_cache-> cpu_slab->freelist 里面。
同时,我们要搞清楚两个 freelist 和一个计数器,一个是 kmem_cache-> cpu_slab->freelist ,一个是 kmem_cache-> cpu_slab-> page-> freelist ,计数器是 kmem_cache-> cpu_slab-> page-> inuse ,这里要弄清楚的是,计数器 inuse 表明此 SLAB 可否被释放了,所以,任何在 kmem_cache-> cpu_slab->freelist 上的对象,都被认为是在使用中的,虽然它们都是空闲的对象。这样,在看代码的时候,你就可以理解,为什么一个刚刚申请了内存的 SLAB ,将它的 kmem_cache-> cpu_slab-> page-> freelist 赋给了 kmem_cache-> cpu_slab->freelist 之后,会将 kmem_cache-> cpu_slab-> page-> freelist 清空为 NULL ,同时 kmem_cache-> cpu_slab-> page-> inuse 被设置为 kmem_cache-> objects ,即所有对象都在使用。而释放的时候,假设一个释放的对象的 page 不是当前 kmem_cache-> cpu_slab-> page 的话,那么这个对象是被释放到 page-> freelist 里的,如果这个 SLAB 的所有对象都是放到了其 page-> freelist 里,即 page-> inuse 等于了 kmem_cache-> objects ,那么这个 SLAB 就可以被释放给内存系统了,因为这个 SLAB 上即没有正在使用的对象了,也不是当前的 SLAB( 因为它的首 Page 不等于 kmem_cache-> cpu_slab-> page) ,故而可以释放。