Slub分配器的来龙去脉( 五 )

slub的frozen(冻结)和unfrozen(解冻)如果cpu1的kcmem_cache_cpu的slab是frozen, 那么cpu1可以从该slab中取出或放回obj,但是cpu2不能从该slab中取obj, 只能把obj还给该slab 。另外,cpu partial上的slab都是frozen状态 。node partial上的slab都是unfrozen 。耗尽kmem_cache_cpu的slab的obj后解冻slab 。
嵌入式物联网需要学的东西真的非常多,千万不要学错了路线和内容,导致工资要不上去!
无偿分享大家一个资料包,差不多150多G 。里面学习内容、面经、项目都比较新也比较全!某鱼上买估计至少要好几十 。
【Slub分配器的来龙去脉】点击这里找小助理0元领取:嵌入式物联网学习资料(头条)

Slub分配器的来龙去脉

文章插图
 

Slub分配器的来龙去脉

文章插图
 
slub分配器框架下图是在读完宋牧春大侠的《图解Slub》后,我也总结了一张Slub分配器框架图,可以大致的看到Slub的框架 。Slub的框架如下图(图片很大,可以放大):
Slub分配器的来龙去脉

文章插图
 
这篇文章(原文链接以置文末)中用了一个通俗易懂的例子来介绍Slub的工作原理,我觉的这个例子很恰当,所以这里继续借举一下 。
每个数组元素对应一种大小的内存,可以把一个kmem_cache结构体看做是一个特定大小内存的零售商,整个Slub系统中有很多个这样的零售商,每个“零售商”只“零售”特定大小的内存,例如:有的“零售商”只"零售"8Byte大小的内存,有的只”零售“16Byte大小的内存 。——引自luken.《linux内核内存管理slub算法(一)原理》
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 */};


推荐阅读