Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1504749
  • 博文数量: 228
  • 博客积分: 1698
  • 博客等级: 上尉
  • 技术积分: 3241
  • 用 户 组: 普通用户
  • 注册时间: 2008-12-24 21:49
个人简介

Linux

文章分类

全部博文(228)

文章存档

2017年(1)

2016年(43)

2015年(102)

2014年(44)

2013年(5)

2012年(30)

2011年(3)

分类: LINUX

2014-12-02 16:11:49

slab分配器是Linux内存管理中非常重要和复杂的一部分,其工作是针对一些经常分配并释放的对象,如进程描述符等,这些对象的大小一般比较小,如果直接采用伙伴系统来进行分配和释放,不仅会造成大量的内碎片,而且处理速度也太慢。而slab分配器是基于对象进行管理的,相同类型的对象归为一类(如进程描述符就是一类),每当要申请这样一个对象,slab分配器就从一个slab列表中分配一个这样大小的单元出去,而当要释放时,将其重新保存在该列表中,而不是直接返回给伙伴系统。slab分配对象时,会使用最近释放的对象内存块,因此其驻留在CPU高速缓存的概率较高。
用于描述和管理cache的数据结构是struct kmem_cache:

点击(此处)折叠或打开

  1. struct kmem_cache {
  2. /* 1) per-cpu data, touched during every alloc/free */
  3.     struct array_cache *array[NR_CPUS];    // 记录本地高速缓存的信息,同时用于跟踪最近释放的对象
  4. /* 2) Cache tunables. Protected by cache_chain_mutex */
  5.     unsigned int batchcount; // 本地高速缓存换入换出的批对象数量
  6.     unsigned int limit;      // 本地高速缓存中空闲对象的最大数量
  7.     unsigned int shared;

  8.     unsigned int buffer_size;    // 管理对象的大小
  9.     u32 reciprocal_buffer_size;  // buff_size的倒数值
  10. /* 3) touched by every alloc & free from the backend */

  11.     unsigned int flags;        /* constant flags */     // 高速缓存的永久标识
  12.     unsigned int num;        /* # of objs per slab */   // 一个slab所包含的对象数目

  13. /* 4) cache_grow/shrink */
  14.     /* order of pgs per slab (2^n) */
  15.     unsigned int gfporder;                              // 一个slab所包含的连续页框数的对数

  16.     /* force GFP flags, e.g. GFP_DMA */
  17.     gfp_t gfpflags;                                     // 与伙伴关系系统交互时提供的分配标识

  18.     size_t colour;            /* cache colouring range */    // 颜色个数
  19.     unsigned int colour_off;    /* colour offset */          // 着色偏移量
  20.     struct kmem_cache *slabp_cache;                     // 如果将slab描述符存储在外部, 指针指向存储slab描述符的cache,否则为NULL
  21.     unsigned int slab_size;                             // slab管理区大小
  22.     unsigned int dflags;        /* dynamic flags */     // 动态标识

  23.     /* constructor func */
  24.     void (*ctor)(void *obj);                            // 创建高速缓存时的构造函数指针

  25. /* 5) cache creation/removal */
  26.     const char *name;                                   // 高速缓存名
  27.     struct list_head next;                              // 用于将高速缓存链入cache chain

  28. /* 6) statistics */
  29. #ifdef CONFIG_DEBUG_SLAB                                // 调试用的变量
  30.     unsigned long num_active;
  31.     unsigned long num_allocations;
  32.     unsigned long high_mark;
  33.     unsigned long grown;
  34.     unsigned long reaped;
  35.     unsigned long errors;
  36.     unsigned long max_freeable;
  37.     unsigned long node_allocs;
  38.     unsigned long node_frees;
  39.     unsigned long node_overflow;
  40.     atomic_t allochit;
  41.     atomic_t allocmiss;
  42.     atomic_t freehit;
  43.     atomic_t freemiss;

  44.     /*
  45.      * If debugging is enabled, then the allocator can add additional
  46.      * fields and/or padding to every object. buffer_size contains the total
  47.      * object size including these internal fields, the following two
  48.      * variables contain the offset to the user object and its size.
  49.      */
  50.     int obj_offset;
  51.     int obj_size;
  52. #endif /* CONFIG_DEBUG_SLAB */

  53.     /*
  54.      * We put nodelists[] at the end of kmem_cache, because we want to size
  55.      * this array to nr_node_ids slots instead of MAX_NUMNODES
  56.      * (see kmem_cache_init())
  57.      * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
  58.      * is statically defined, so we reserve the max number of nodes.
  59.      */
  60.     struct kmem_list3 *nodelists[MAX_NUMNODES];            // 用于组织该高速缓存中的slab
  61.     /*
  62.      * Do not add fields after nodelists[]
  63.      */
  64. };

点击(此处)折叠或打开

  1. /*
  2.  * The slab lists for all objects.
  3.  */
  4. struct kmem_list3 {
  5.     struct list_head slabs_partial;    /* partial list first, better asm code */ // 包含空闲和已分配对象的slab描述符
  6.     struct list_head slabs_full;                                                 // 包含非空闲的slab描述符
  7.     struct list_head slabs_free;                                                 // 包含空闲的slab描述符
  8.     unsigned long free_objects;                                                  // 高速缓存中空闲对象的个数
  9.     unsigned int free_limit;                                                     // 空闲对象的上限
  10.     unsigned int colour_next;    /* Per-node cache coloring */                   // 下一个slab使用的颜色    
  11.     spinlock_t list_lock;
  12.     struct array_cache *shared;    /* shared per node */
  13.     struct array_cache **alien;    /* on other nodes */
  14.     unsigned long next_reap;    /* updated without locking */
  15.     int free_touched;        /* updated without locking */
  16. };
描述和管理单个slab的结构是struct slab

点击(此处)折叠或打开

  1. /*
  2.  * struct slab
  3.  *
  4.  * Manages the objs in a slab. Placed either at the beginning of mem allocated
  5.  * for a slab, or allocated from an general cache.
  6.  * Slabs are chained into three list: fully used, partial, fully free slabs.
  7.  */
  8. struct slab {
  9.     struct list_head list;        // 用于将slab链入kmem_list3的链表
  10.     unsigned long colouroff;      // 该slab的着色偏移
  11.     void *s_mem;        /* including colour offset */        // 指向slab中的第一个对象
  12.     unsigned int inuse;    /* num of objs active in slab */  // 已分配出去的对象
  13.     kmem_bufctl_t free;           // 下一个空闲对象的下标
  14.     unsigned short nodeid;        // 节点标识号
  15. };
还要介绍的一个数据结构就是struct array_cache。struct kmem_cache中定义了一个struct array_cache指针数组,数组的元素个数对应了系统的CPU数,和伙伴系统中的每CPU页框高速缓存类似,该结构用来描述每个CPU的本地高速缓存,它可以减少SMP系统中对于自旋锁的竞争。在每个array_cache的末端都用一个指针数组记录了slab中的空闲对象,分配对象时,采用LIFO方式,也就是将该数组中的最后一个索引对应的对象分配出去,以保证该对象还驻留在高速缓存中的可能性。实际上,每次分配内存都是直接与本地CPU高速缓存进行交互,只有当其空闲内存不足时,才会从kmem_list中的slab中引入一部分对象到本地高速缓存中,而kmem_list中的空闲对象也不足了,那么就要从伙伴系统中引入新的页来建立新的slab了,这一点也和伙伴系统的每CPU页框高速缓存很类似。

点击(此处)折叠或打开

  1. /*
  2.  * struct array_cache
  3.  *
  4.  * Purpose:
  5.  * - LIFO ordering, to hand out cache-warm objects from _alloc
  6.  * - reduce the number of linked list operations
  7.  * - reduce spinlock operations
  8.  *
  9.  * The limit is stored in the per-cpu structure to reduce the data cache
  10.  * footprint.
  11.  *
  12.  */
  13. struct array_cache {
  14.     unsigned int avail;        // 本地高速缓存中可用的空闲对象数
  15.     unsigned int limit;        // 空闲对象上限
  16.     unsigned int batchcount;   // 一次转入/转出的对象数量
  17.     unsigned int touched;      // 标识本地CPU最近是否被使用
  18.     spinlock_t lock;
  19.     void *entry[];    /*       // 用于跟踪空闲对象指针数组的访问
  20.              * Must have this definition in here for the proper
  21.              * alignment of array_cache. Also simplifies accessing
  22.              * the entries.
  23.              */
  24. };
slab分配器涉及到了一些繁杂的概念,这些在后面再逐一结合代码进行讲解,在理解slab分配器的工作之前,必须先理解上述这些数据结构之间的联系,下图给出了一个清晰的描述。



阅读(1504) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~