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. Spark-Cache与Checkpoint

    一.Cache缓存操作 scala> val rdd1 = sc.textFile("hdfs://192.168.146.111:9000/logs") rdd1: org ...

  2. SP11469 SUBSET-Balanced Cow Subsets meet-in-the-middle+状压

    正解:折半搜索 解题报告: 传送门! 这题我开始看到的时候贼开心地就把这题的代码直接粘过来辣 然后就T辣,,,仔细思考一下,为什么呢? 因为会枚举到很多相同的状态 举个eg 20 1 1 1 1 1 ...

  3. 洛谷P1903 数颜色 [国家集训队] 莫队

    正解:带修莫队 解题报告: 可以理解为引入时间参数,然后就是有了仨参数,关于这个修改同样的是,如果时间是相同的,不用搞,如果时间不相同做一下时光倒流/时光推移就成嘛 但是肯定既然这样的话,按照原来的s ...

  4. JS模块化编程(四)--require应用

    获取&使用require.js 下载最新版的Require.JS.下载之后,把它放在项目的脚本文件夹下,比如 js 文件夹下,项目结构看上去应该是: 要充分使用Require.JS,将html ...

  5. Java-mybatis-一次执行多条SQL语句

    mysql数据库 1.修改数据库连接参数加上allowMultiQueries=true,如: hikariConfig.security.jdbcUrl=jdbc:mysql://xx.xx.xx: ...

  6. abap关键字

    1:abap将提升的关键字快捷输入 按tab键,提示的关键字将会自动输入. 2:shift tab 用于对其格式 3:ctrl+d 将改行复制到下一行.

  7. Spark SQL初始化和创建DataFrame的几种方式

    一.前述       1.SparkSQL介绍 Hive是Shark的前身,Shark是SparkSQL的前身,SparkSQL产生的根本原因是其完全脱离了Hive的限制. SparkSQL支持查询原 ...

  8. HDU 5059 Help him(简单模拟题)

    http://acm.hdu.edu.cn/showproblem.php?pid=5059 题目大意: 给定一个字符串,如果这个字符串是一个整数,并且这个整数在[a,b]的范围之内(包括a,b),那 ...

  9. 下载YouTube视频的方法

    这个网站就可以: http://www.clipconverter.cc/ 更多的网站及介绍参考知乎:http://www.zhihu.com/question/19964181

  10. iqueryable lambda表达式

    1.groupby 1.group by var newLaborDtos = laborDtos.GroupBy(s => new { s.FinancingAmount, s.Company ...