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

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

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

struct kmem_cache *kmalloc_caches[KMALLOC_SHIFT_HIGH + 1] __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(3)))

      __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中找到   

1            #ifndef RO_AFTER_INIT_DATA
2     #define RO_AFTER_INIT_DATA \ 
3     __start_ro_after_init = .; \ 
4     *(.data..ro_after_init) \
5     __end_ro_after_init = .;
6     #endif        
View Code

相关文章:

  • 2022-01-17
  • 2022-12-23
  • 2021-04-03
  • 2022-12-23
  • 2021-08-06
  • 2021-06-04
  • 2021-11-24
  • 2021-11-26
猜你喜欢
  • 2021-07-04
  • 2022-12-23
  • 2022-12-23
  • 2022-01-08
  • 2021-05-30
相关资源
相似解决方案