Linux SLUB分配器详解
_cache 全局变量指向kmem_cache 对象缓冲区的 kmem_cache 对象.每个 slab 都需要一个类型为 struct slab 的描述符数据结构管理其状态,同时还需要一个 kmem_bufctl_t(被定义为无符号整数)的结构数组来管理空闲对象.如果对象不超过 1/8 个物理内存页框的大小,那么这些 slab 管理结构直接存放在 slab 的内部,位于分配给 slab 的第一个物理内存页框的起始位置;否则的话,存放在 slab 外部,位于由 kmalloc 分配的通用对象缓冲区中. slab 中的对象有 2 种状态:已分配或空闲.为了有效地管理 slab,根据已分配对象的数目,slab 可以有 3 种状态,动态地处于缓冲区相应的队列中: Full 队列,此时该 slab 中没有空闲对象. Partial 队列,此时该 slab 中既有已分配的对象,也有空闲对象. Empty 队列,此时该 slab 中全是空闲对象. NUMA(Non Uniform Memory Access) 系统中,每个节点都会拥有这 3 种 slab 队列,struct kmem_list3结构用于维护相关队列.SLAB 分配器优先从 Partial 队列里的 slab 中分配对象.当 slab 的一个已分配对象被释放时,该 slab 从 Partial 队列转移到 Empty 队列;当 slab 的一个空闲对象被分配时,该 slab 从Partial 队列转移到Full 队列里.缓冲区中空闲对象总数不足时,则分配更多的 slab;但是如果空闲对象比较富余,Empty 队列的部分 slab 将被定期回收. 为了充分利用硬件高速缓存,SLAB 分配器允许对象在一级硬件高速缓存中对齐(创建缓冲区时,设置 SLAB_HWCACHE_ALIGN 标志);同时使用着色(color)策略,同一缓冲区内不同 slab 中相同编号的对象的地址相互错开,避免它们被放入同一物理高速缓存行而造成频繁换入/换出的性能损失. 为了支持多处理器同时分配对象,缓冲区为每个处理器维护一个本地缓存.处理器直接从本地缓存中分配对象,从而避免了锁的使用;当本地缓存为空时,从 slab 中批量分配对象到本地缓存. -------------------------------------------------------------------------------- SLUB 分配器的设计原理 SLAB 分配器多年以来一直位于 Linux 内核的内存管理部分的核心地带,内核黑客们一般不愿意主动去更改它的代码,它实在是非常复杂,在大多数情况下,它的工作完成的相当不错.但是,随着大规模多处理器系统和 NUMA系统的广泛应用,SLAB 分配器逐渐暴露出自身的严重不足: 较多复杂的队列管理.在 SLAB 分配器中存在众多的队列,例如针对处理器的本地对象缓存队列,slab 中空闲对象队列,每个 slab 处于一个特定状态的队列中,甚至缓冲区控制结构也处于一个队列之中.有效地管理这些不同的队列是一件费力且复杂的工作. slab 管理数据和队列的存储开销比较大.每个 slab 需要一个 struct slab 数据结构和一个管理所有空闲对象的 kmem_bufctl_t(4 字节的无符号整数)的数组.当对象体积较少时,kmem_bufctl_t 数组将造成较大的开销(比如对象大小为32字节时,将浪费 1/8 的空间).为了对象在硬件高速缓存中对齐和使用着色策略,还浪费额外的内存.同时,缓冲区针对节点和处理器的队列也会浪费不少内存.测试表明在一个 1000 节点/处理器的大规模 NUMA 系统中,数 GB 内存被用来维护队列和对象的引用. 缓冲区内存回收比较复杂. 对 NUMA 的支持非常复杂.SLAB 对 NUMA 的支持基于物理页框分配器,无法细粒度地使用对象,因此不能保证处理器级缓存的对象来自同一节点. 冗余的 Partial 队列.SLAB 分配器针对每个节点都有一个 Partial 队列,随着时间流逝,将有大量的 Partial slab 产生,不利于内存的合理使用. 性能调优比较困难.针对每个 slab 可以调整的参数比较复杂,分配处理器本地缓存时,不得不使用自旋锁. 调试功能比较难于使用. 为了 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |