zoukankan      html  css  js  c++  java
  • [Linux内存]slab分配器学习笔记(一)--概念

    http://blog.csdn.net/vanbreaker/article/details/7664296
    1,为什么需要slab分配器:
     利用伙伴系统进行分配内存只能按照页的单位进行分配,这样会造成很多的内存浪费,多了很多内存碎片,比如只需要申请10字节的,结果分配了一个页。
     
    2,slab分配器和伙伴系统分配的差别
     slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,因此其驻留在CPU高速缓存的概率较高
     Slab分配器由很多缓存(动态链表)组成,不同的缓存大小不同(如名为kmalloc-128的缓存所管理对象的长度为128字节)。Linux的Slab缓存分为专用和通用两种,通用缓存通过函数kmem_cache_init() 进行初始化,适用于特定对象,比如各种描述符,存放进程描述符的缓存大小就是sizeof(task_struct);而专用缓存则通过函数 kmem_cache_create()创建。通用Slab的对象大小预先定义好的,一般是2的次幂(cache对齐的需要),Linux使用13级, 如下:32、64、128、256、512、1024、2048、4096、8192、16384、32768、65536、131072。这样可以保证内存碎片小于百分之50


    3,slab的概念

    slab分配器把内存区看作对象(object),这些对象由一组数据结构和几个构造函数或者析构函数组成,分别用于初始化和回收内存。slab分配器把对象分组放进告诉缓存,包含高速缓存的主内存区被划分为多个slab,每个slab由一个或者多个连续的页组成,这些页框包含已分配对象和空闲对象。

    每一个slab对象都有一个kmem_bufctl_t描述符,每个slab的对象描述符都存放在slab描述符的后面。因此((kmem_bufctl_t*)(slab + 1)就指向slab的kmem_bufctl_t描述符地址,语句((kmem_bufctl_t*)(slab + 1)[i]就是访问第i个对象的索引。


    4,slab分配器用的相关数据结构
    用于描述和管理cache的数据结构是struct kmem_cache

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. struct kmem_cache {    
    2. /* 1) per-cpu data, touched during every alloc/free */    
    3.     /*per-CPU数据,记录了本地高速缓存的信息,也用于跟踪最近释放的对象,每次分配和释放都要直接访问它*/    
    4.     struct array_cache *array[NR_CPUS];     
    5. /* 2) Cache tunables. Protected by cache_chain_mutex */    
    6.     unsigned int batchcount;  /*本地高速缓存转入或转出的大批对象数量*/    
    7.     unsigned int limit;       /*本地高速缓存中空闲对象的最大数目*/    
    8.     unsigned int shared;    
    9.     
    10.     unsigned int buffer_size;/*管理对象的大小*/    
    11.     u32 reciprocal_buffer_size;/*buffer_size的倒数值*/    
    12. /* 3) touched by every alloc & free from the backend */    
    13.     
    14.     unsigned int flags;          /* 高速缓存的永久标识*/    
    15.     unsigned int num;         /* 一个slab所包含的对象数目 */    
    16.     
    17. /* 4) cache_grow/shrink */    
    18.     /* order of pgs per slab (2^n) */    
    19.     unsigned int gfporder;   /*一个slab包含的连续页框数的对数*/    
    20.      
    21.     /* force GFP flags, e.g. GFP_DMA */    
    22.     gfp_t gfpflags;          /*与伙伴系统交互时所提供的分配标识*/    
    23.     
    24.     size_t colour;         /* 颜色的个数*/    
    25.     unsigned int colour_off; /* 着色的偏移量 */    
    26.         
    27.     /*如果将slab描述符存储在外部,该指针指向存储slab描述符的cache,  
    28.       否则为NULL*/    
    29.     struct kmem_cache *slabp_cache;    
    30.     unsigned int slab_size;  /*slab管理区的大小*/    
    31.     unsigned int dflags;     /*动态标识*/    
    32.     
    33.     void (*ctor)(void *obj); /*创建高速缓存时的构造函数指针*/    
    34.     
    35. /* 5) cache creation/removal */    
    36.     const char *name;         /*高速缓存名*/    
    37.     struct list_head next;    /*用于将高速缓存链入cache chain*/    
    38.     
    39. /* 6) statistics */    
    40.      
    41.      /*struct kmem_list3用于组织该高速缓存中的slab*/    
    42.     struct kmem_list3 *nodelists[MAX_NUMNODES];    
    43.     /*  
    44.      * Do not add fields after nodelists[]  
    45.      */    
    46. };   
    47.   
    48. struct kmem_list3 {    
    49.     struct list_head slabs_partial;/*slab链表,包含空闲对象和已分配对象的slab描述符*/    
    50.     struct list_head slabs_full;   /*slab链表,只包含非空闲的slab描述符*/    
    51.     struct list_head slabs_free;   /*slab链表,只包含空闲的slab描述符*/    
    52.     unsigned long free_objects;    /*高速缓存中空闲对象的个数*/    
    53.     unsigned int free_limit;       /*空闲对象的上限*/    
    54.     unsigned int colour_next;       /*下一个slab使用的颜色*/    
    55.     spinlock_t list_lock;    
    56.     struct array_cache *shared; /* shared per node */    
    57.     struct array_cache **alien; /* on other nodes */    
    58.     unsigned long next_reap;    /* updated without locking */    
    59.     int free_touched;       /* updated without locking */    
    60. };    
    61.   
    62. 描述和管理单个slab的结构是struct slab  
    63. struct slab {    
    64.     struct list_head list;  /*用于将slab链入kmem_list3的链表*/    
    65.     unsigned long colouroff;/*该slab的着色偏移*/    
    66.     void *s_mem;            /*指向slab中的第一个对象*/    
    67.     unsigned int inuse;     /*已分配出去的对象*/    
    68.     kmem_bufctl_t free;     /*下一个空闲对象的下标*/    
    69.     unsigned short nodeid;  /*节点标识号*/    
    70. };   


     slab描述符可以放在以下两个地方
    1,外部slab描述符,存在普通的高速缓存
    2,内部slab描述符,位于分配给slab的第一个页框的起始位置

    struct kmem_cache中定义了一个struct array_cache指针数组,数组的元素个数对应了系统的CPU数,和伙伴系统中的每CPU页框高速缓存类似,该结构用来描述每个CPU的本地高速缓存,在每个array_cache的末端都用一个指针数组记录了slab中的空闲对象,分配对象时,采用LIFO方式,也就是将该数组中的最后一个索引对应的对象分配出去,以保证该对象还驻留在高速缓存中的可能性。实际上,每次分配内存都是直接与本地CPU高速缓存进行交互,只有当其空闲内存不足时,才会从kmem_list中的slab中引入一部分对象到本地高速缓存中,而kmem_list中的空闲对象也不足了,那么就要从伙伴系统中引入新的页来建立新的slab了,这一点也和伙伴系统的
    每CPU页框高速缓存很类似。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
      1. struct array_cache {    
      2.     unsigned int avail;/*本地高速缓存中可用的空闲对象数*/    
      3.     unsigned int limit;/*空闲对象的上限*/    
      4.     unsigned int batchcount;/*一次转入和转出的对象数量*/    
      5.     unsigned int touched;   /*标识本地CPU最近是否被使用*/    
      6.     spinlock_t lock;    
      7.     void *entry[];  /*这是一个伪数组,便于对后面用于跟踪空闲对象的指针数组的访问   
      8.              */    
      9. };   
  • 相关阅读:
    剑指offer字符串列表
    剑指offer数组3
    剑指offer数组2
    剑指offer数组1
    剑指offer数组列表
    tensorflow+ssd_mobilenet实现目标检测的训练
    Win7+keras+tensorflow使用YOLO-v3训练自己的数据集
    Java是如何实现跨平台的
    Xshell 、PuTTY 复制文件到Linux
    Asp.Net Core2.0在linux下发布
  • 原文地址:https://www.cnblogs.com/zhiliao112/p/4251225.html
Copyright © 2011-2022 走看看