1. 分析的linux内核源码版本为4.18.0

2. 与slub相关的内核配置项为CONFIG_SLUB

3. 一切都从一个结构体数组kmalloc_caches开始,它的原型如下:

struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + ] __ro_after_init;

  3.1 这个数组定义在mm/slab_common.c中

  3.2 KMALLOC_SHIFT_HIGH是如何定义的呢? 

#define KMALLOC_SHIFT_HIGH  (PAGE_SHIFT + 1)
#define PAGE_SHIFT  12 (各个架构下的定义都有些差异,如果是arm64,那么是通过CONFIG_ARM64_PAGE_SHIFT来指定的,这个配置项在arch/arm64/Kconfig文件中定义,默认为12,也就是默认页面大小为4KiB,笔者以arm64为例)

    那么KMALLOC_SHIFT_HIGH=PAGE_SHIFT + 1 = 12 + 1 = 13,KMALLOC_SHIFT_HIGH+1=13+ 1= 14说明kmalloc_caches数组中有14个元素,每个元素是kmem_cache这个结构体

  3.3 分析一下sturct kmem_cache这个结构体

     

  /*
* Slab cache management.
*/
struct kmem_cache {
struct kmem_cache_cpu __percpu *cpu_slab;
/* Used for retriving partial slabs etc */
slab_flags_t flags;
unsigned long min_partial;
unsigned int size; /* The size of an object including meta data */
unsigned int object_size;/* The size of an object without meta data */
unsigned int offset; /* Free pointer offset. */
#ifdef CONFIG_SLUB_CPU_PARTIAL
/* Number of per cpu partial objects to keep around */
unsigned int cpu_partial;
#endif
struct kmem_cache_order_objects oo; /* Allocation and freeing of slabs */
struct kmem_cache_order_objects max;
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 *);
unsigned int inuse; /* Offset to metadata */
unsigned int align; /* Alignment */
unsigned int red_left_pad; /* Left redzone padding size */
const char *name; /* Name (only for display!) */
struct list_head list; /* List of slab caches */
#ifdef CONFIG_SYSFS
struct kobject kobj; /* For sysfs */
struct work_struct kobj_remove_work;
#endif
#ifdef CONFIG_MEMCG
struct memcg_cache_params memcg_params;
/* for propagation, maximum size of a stored attr */
unsigned int max_attr_size;
#ifdef CONFIG_SYSFS
struct kset *memcg_kset;
#endif
#endif #ifdef CONFIG_SLAB_FREELIST_HARDENED
unsigned long random;
#endif #ifdef CONFIG_NUMA
/*
* Defragmentation by allocating from a remote node.
*/
unsigned int remote_node_defrag_ratio;
#endif #ifdef CONFIG_SLAB_FREELIST_RANDOM
unsigned int *random_seq;
#endif #ifdef CONFIG_KASAN
struct kasan_cache kasan_info;
#endif unsigned int useroffset; /* Usercopy region offset */
unsigned int usersize; /* Usercopy region size */ struct kmem_cache_node *node[MAX_NUMNODES];
};

  3.4 struct kmem_cache中有哪些域是需要关注到的呢?

    3.4.1 node

      struct kmem_cache_node *node[MAX_NUMNODES]; 

      这里面MAX_NUMNODES定义如下:

    

      #define MAX_NUMNODES    (1 << NODES_SHIFT)

      那么NODES_SHIFT又是如何定义的呢?

    

      #ifdef CONFIG_NODES_SHIFT
      #define NODES_SHIFT CONFIG_NODES_SHIFT
      #else
      #define NODES_SHIFT 0
      #endif

      如果定义了CONFIG_NODES_SHIFT,那么NODES_SHIFT就等于CONFIG_NODES_SHIFT的值;

      如果未定义CONFIG_NODES_SHIFT,那么NODES_SHIFT就等于0;

      假设未定义CONFIG_NODES_SHIFT,那么MAX_NUMNODES就等于1,也就是只有一个kmem_cache_node节点.

    3.4.2 cpu_slab

      

      struct kmem_cache_cpu __percpu *cpu_slab;

      表示每个cpu都具有一个这个的结构来描述当前slab的情况

      

      __percpu是什么?

      

      # define __percpu   __attribute__((noderef, address_space()))

      __percpu表示一种特性,是用来修饰变量的.noderef指定这个变量必须是有效的,address_space(3)则指定变量所在的地址空间为3,也就是cpu空间.作用就是保证每个cpu都有这个变量的副本

    3.4.3 size

      

      unsigned int size;  /* The size of an object including meta data */

      表示包含元数据的一个object的大小

    3.4.4 object_size

      

      unsigned int object_size;/* The size of an object without meta data */

      表示不包含元数据的一个object的大小

    3.4.5 offset

      
      unsigned int offset;    /* Free pointer offset. */

      表示空闲指针的偏移量

  3.5 __ro_after_init是什么东西?      

    #define __ro_after_init __attribute__((__section__(".data..ro_after_init")))

    这是一个宏,定义在include/linux/cache.h中,被用来标记初始化之后只读的内容

    这里面涉及到一个段.data..ro_after_init,可以在include/asm-generic/vmlinux.lds.h中找到   

            #ifndef RO_AFTER_INIT_DATA
    #define RO_AFTER_INIT_DATA \
    __start_ro_after_init = .; \
    *(.data..ro_after_init) \
    __end_ro_after_init = .;
    #endif    

4.  如何填充kmalloc_caches数组的呢?

  start_kernel()-> (init/main.c)

      mm_init()->  (init/main.c)

        kmem_cache_init()->  (mm/slub.c)

          create_kmalloc_caches()-> (mm/slab_common.c)

            new_kamalloc_cache()-> (mm/slab_common.c)

              create_kmalloc_cache()-> (mm/slab_common.c)

  从源码中可以得知kmalloc_caches数组由create_kmalloc_cache()填充每一个数组中的元素

5. slub中支持的object的大小范围是多少?

  每个kmalloc_caches中的元素会使用结构体kmem_cache中的域size和objsize来指定slab中每个object的大小,object的大小从全局常量结构体数组kmalloc_info中获取

  const struct kmalloc_info_struct kmalloc_info[] __initconst = {
{NULL, }, {"kmalloc-96", },
{"kmalloc-192", }, {"kmalloc-8", },
{"kmalloc-16", }, {"kmalloc-32", },
{"kmalloc-64", }, {"kmalloc-128", },
{"kmalloc-256", }, {"kmalloc-512", },
{"kmalloc-1024", }, {"kmalloc-2048", },
{"kmalloc-4096", }, {"kmalloc-8192", },
{"kmalloc-16384", }, {"kmalloc-32768", },
{"kmalloc-65536", }, {"kmalloc-131072", },
{"kmalloc-262144", }, {"kmalloc-524288", },
{"kmalloc-1048576", }, {"kmalloc-2097152", },
{"kmalloc-4194304", }, {"kmalloc-8388608", },
{"kmalloc-16777216", }, {"kmalloc-33554432", },
{"kmalloc-67108864", }
};

  从数组中的最后一个元素可以获知支持的最大object的大小为2^26=64MiB,但是从以下代码分析:

  void __init create_kmalloc_caches(slab_flags_t flags)
{
int i; for (i = KMALLOC_SHIFT_LOW; i <= KMALLOC_SHIFT_HIGH; i++) {
if (!kmalloc_caches[i])
new_kmalloc_cache(i, flags);

  可得:

    kmalloc_caches数组中仅下标为KMALLOC_SHIFT_LOW到KMALLOC_SHIFT_HIGH的元素才被初始化,

    也就是从3->13支持的最小object大小为2^3=8字节,最大object大小为2^13=8KiB,说明kmalloc_caches数组的前三个元素并没有被初始化,仅初始化数组的后面11个元素.

    从以上分析可得slub支持的最大object的大小为页面大小的两倍(PAGE_SIZE*2),页面大小为4KiB,那么最大object的大小为4KiB * 2 = 8KiB

                  

 

分析linux内核中的slub内存管理算法的更多相关文章

  1. Linux内核中常用的数据结构和算法(转)

    知乎链接:https://zhuanlan.zhihu.com/p/58087261 Linux内核代码中广泛使用了数据结构和算法,其中最常用的两个是链表和红黑树. 链表 Linux内核代码大量使用了 ...

  2. linux内核中的C语言常规算法(前提:你的编译器要支持typeof和type)

    学过C语言的伙伴都知道,曾经比较两个数,输出最大或最小的一个,或者是比较三个数,输出最大或者最小的那个,又或是两个数交换,又或是绝对值等等,其实这些算法在linux内核中通通都有实现,以下的代码是我从 ...

  3. Linux内核入门到放弃-内存管理-《深入Linux内核架构》笔记

    概述 内存管理的实现涵盖了许多领域: 内存中的物理内存页管理 分配大块内存的伙伴系统 分配较小内存块的slab.slub和slob分配器 分配非连续内存块的vmalloc机制 进程的地址空间 在IA- ...

  4. Linux内核设计笔记12——内存管理

    内存管理学习笔记 页 页是内核管理内存的基本单位,内存管理单元(MMU,管理内存并把虚拟地址转化为物理地址的硬件)通常以页为单位进行处理,从虚拟内存的角度看,页就是最小单位. struct page{ ...

  5. 分析Linux内核中进程的调度(时间片轮转)-《Linux内核分析》Week2作业

    1.环境的搭建: 这个可以参考孟宁老师的github:mykernel,这里不再进行赘述.主要是就是下载Linux3.9的代码,然后安装孟宁老师编写的patch,最后进行编译. 2.代码的解读 课上的 ...

  6. linux内核(四)内存管理单元MMU

    1,基本概念 一个程序运行时没必要全部都同时装入内存,只需要把当前需要运行的部分装入内存即可,这样就使得一个大程序可以在较小的内存中运行,也使得内存中可以同时装入更多的程序并发执行,从用户角度看,该系 ...

  7. Linux内核中的有关Page的算法

    static inline int get_order(unsigned long size) { int order; size = (size-1) >> (PAGE_SHIFT-1) ...

  8. Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches Slab内存管理机制 SLUB内存管理机制

    Linux中的Buffer Cache和Page Cache echo 3 > /proc/sys/vm/drop_caches   Slab内存管理机制 SLUB内存管理机制 http://w ...

  9. Linux内核中的GPIO系统之(3):pin controller driver代码分析

    一.前言 对于一个嵌入式软件工程师,我们的软件模块经常和硬件打交道,pin control subsystem也不例外,被它驱动的硬件叫做pin controller(一般ARM soc的datash ...

随机推荐

  1. pandas1

    https://www.cnblogs.com/nxld/p/6058591.html

  2. Distribution(F题)---第八届河南省程序设计大赛

    Description One day , Wang and Dong in the Dubai desert expedition, discovered an ancient castle. Fo ...

  3. Python开发【笔记】:加锁的最佳方案

    避开死锁 代码程序中,尽量要避免死锁的产生,下面分析常见的线程锁使用方式 :注:只有同一把锁才会产生互斥 1.常见的死锁方式(加锁时程序报错,锁未释放): import time import thr ...

  4. 理解CopyOnWriteArrayList

    CopyOnWriteArrayList,顾名思义,Write的时候总是要Copy,也就是说对于任何可变的操作(add.set.remove)都是伴随复制这个动作的 A thread-safe var ...

  5. 订阅号助手App发布 手机也能管理公众号了

    盼着许久的微信订阅号助手app终于发布了!“ 微信团队发布「订阅号助手」App,支持公众号运营者在手机上发表内容.查看和回复消息.管理已关注用户和帐号.暂时只支持iOS平台,Android平台敬请期待 ...

  6. linux下面发布80端口的服务

    1:linux下面发布端口号为80 的服务,要在root用户下面发布.否则提示权限不够 2:在普通用户下面配置的java环境,在root用户下面不可用. 解决方法:2.1  要使用source /et ...

  7. mount –o remount,rw /

    mount –o remount,rw / 重新挂载为已经挂载了的文件系统(以读写权限挂载),需要注意的是,挂载点必须是一个已经存在的目录,这个目录可以不为空.一般用于此目录下的文件为ro权限,需要临 ...

  8. hdu1305Immediate Decodability(字典树)

    这题看是否 这题能A是侥幸,解决的办法是先存一下输入的字符串,进行排序. Problem Description An encoding of a set of symbols is said to ...

  9. 什么是anaconda【转载】

    转自:https://zhidao.baidu.com/question/525102108723657245.html https://zhidao.baidu.com/question/62475 ...

  10. 蒙特卡洛模拟(Monte Carlo simulation)

    1.蒙特卡罗模拟简介 蒙特卡罗模拟,也叫统计模拟,这个术语是二战时期美国物理学家Metropolis执行曼哈顿计划的过程中提出来的,其基本思想很早以前就被人们所发现和利用.早在17世纪,人们就知道用事 ...