slab、slob和slub关系slab、slob和slub都是小内存分配器,slab是slob和slub实现的基础,而slob和slub是针对slab在不同场景下的优化版本 。在slab引入Linux的很多年内,其都是Linux内核管理对象缓冲区的主流算法 。并且由于slab的实现非常复杂,很长一段时间内都少有对它的改动 。随着多处理器的发展和NUMA架构的广泛应用,slab的不足也逐渐显现 。slab的缓存队列管理复杂,其用于管理的数据结构存储开销大,对NUMA支持复杂,slab着色机制效果不明显 。这些不足让slab很难在两种场景下提供最优的性能:小型嵌入式系统和配备有大量物理内存的大规模并行系统 。对于小型嵌入式系统来说,slab分配器的代码量和复杂性都太高;对于大规模并行系统,slab用于自身管理的数据结构就需要占用很多G字节内存 。针对slab的不足,内核开发人员Christoph Lameter在在内核版本2.6开发期间,引入了新的Slub分配器 。Slub简化了slab一些复杂的设计,但保持slab的基本设计思想 。同时,一种新的针对小型嵌入式系统的分配器slob也被引入,为了适应嵌入式系统的特点,slob进行了特别的优化,以大幅减少代码量(slob只有大约600行代码) 。
slab层在内存管理子系统的层次slab层可以理解为一个通用层,其包含了slab、slob和slub,至于底层具体使用哪种分配器可以通过配置内核选项进行选择 。对于内核的其他模块,则不需要关注底层使用了哪个分配器 。因为为了保证内核的其他模块都可以无缝迁移到Slub/slob,所有分配器的接口都是相同的,它们都实现了一组特定的接口用于内存分配 。下图为Slab层在内存管理中的层次图:

文章插图
逻辑上看,slab层位于伙伴系统之上 。因为Buddy是最底层的分配器,Slub需要先向Buddy申请内存,而不能越过Buddy获取page 。从Buddy申请到内存后,Slub才可以对其进行自己的操作 。
slub分配器框架下图是在读完宋牧春大侠的《图解Slub》后,我也总结了一张Slub分配器框架图,可以大致的看到Slub的框架 。Slub的框架如下图(图片很大,可以放大):

文章插图
这篇文章(原文链接以置文末)中用了一个通俗易懂的例子来介绍Slub的工作原理,我觉的这个例子很恰当,所以这里继续借举一下 。
每个数组元素对应一种大小的内存,可以把一个kmem_cache结构体看做是一个特定大小内存的零售商,整个Slub系统中有很多个这样的零售商,每个“零售商”只“零售”特定大小的内存,例如:有的“零售商”只"零售"8Byte大小的内存,有的只”零售“16Byte大小的内存 。——引自luken.《linux内核内存管理slub算法(一)原理》Slub的工作原理和日常生产生活的产销环节很类似,所以为了清晰直观的看到其工作原理,我把这个过程画了一幅图来表示,如下图:

文章插图
每个零售商(kmem_cache)有两个“部门”,一个是“仓库”:kmem_cache_node,一个“营业厅”:kmem_cache_cpu 。“营业厅”里只保留一个slab,只有在营业厅(kmem_cache_cpu)中没有空闲内存的情况下才会从仓库中换出其他的slab 。所谓slab就是零售商(kmem_cache)批发的连续的整页内存,零售商把这些整页的内存分成许多小内存,然后分别“零售”出去,一个slab可能包含多个连续的内存页 。slab的大小和零售商有关 。——引自luken.《linux内核内存管理slub算法(一)原理》总的来说,Slub就相当于零售商,它从伙伴系统“批发”内存,然后再零售出去 。
slub的重要数据结构
- kmem_cache
struct kmem_cache {struct kmem_cache_cpu __percpu *cpu_slab;/* Used for retriving partial slabs etc */unsigned long flags;unsigned long min_partial;/* size = object_size + 对象后面下个空闲对象的指针的size */int size;/* The size of an object including meta data */int object_size;/* The size of an object without meta data *//* object首地址 + offset = 下一个空闲对象的指针地址 */int offset;/* Free pointer offset. */int cpu_partial;/* Number of per cpu partial objects to keep around *//** oo表示存放最优slab的order和object的数量* 低16位表示对象数,高16位表示slab的order*/struct kmem_cache_order_objects oo;/* Allocation and freeing of slabs */struct kmem_cache_order_objects max;/** 最小slab只需要足够存放一个对象 。当设备长时间运行以后,内存碎片化严重,* 分配连续物理页很难成功,如果分配最优slab失败,就分配最小slab 。*/struct kmem_cache_order_objects min;gfp_t allocflags;/* gfp flags to use on each alloc */int refcount;/* Refcount for slab cache destroy */void (*ctor)(void *);int inuse;/* Offset to metadata */int align;/* Alignment */// 当slab长度不是对象长度的整数倍的时候,尾部有剩余部分,保存在reserved中int reserved;/* Reserved bytes at the end of slabs */const char *name;/* Name (only for display!) */struct list_head list;/* List of slab caches */int red_left_pad;/* Left redzone padding size */#ifdef CONFIG_SYSFSstruct kobject kobj;/* For sysfs */#endif#ifdef CONFIG_MEMCGstruct memcg_cache_params memcg_params;int max_attr_size; /* for propagation, maximum size of a stored attr */#ifdef CONFIG_SYSFSstruct kset *memcg_kset;#endif#endif#ifdef CONFIG_NUMA/** Defragmentation by allocating from a remote node.*/int remote_node_defrag_ratio;#endif#ifdef CONFIG_SLAB_FREELIST_RANDOMunsigned int *random_seq;#endif#ifdef CONFIG_KASANstruct kasan_cache kasan_info;#endifstruct kmem_cache_node *node[MAX_NUMNODES]; /* 每个NUMA节点都有一个kmem_cache_node */};
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 字节跳动宣布开源 KubeWharf,一个实践驱动的云原生项目集
- 机器人避障中的超声波传感器
- 改善Java代码的八个建议
- 制作红、蓝底色的证件照,学会Word三步搞定,告别PS软件
- 用break模拟python的while循环,验证go语言for循环关键机制
- Apache OpenOffice 4.1.13发布 - 是的,它还在更新
- 网络工程师的Python之路——Netmiko终极指南
- 一种千万级用户实时统计用户数的简单实现
- 扩展你的KUBECTL功能
- 汤姆索亚历险记的故事内容及故事情节 汤姆索亚历险记故事梗概是什么
