linux Slob内存管理小析

来源:互联网 发布:数据结构查找算法总结 编辑:程序博客网 时间:2024/05/16 15:18

Slob分配对象大小是从三个链中选择的

static LIST_HEAD(free_slob_small);

static LIST_HEAD(free_slob_medium);

static LIST_HEAD(free_slob_large);

 

对于小于256字节的对象,将从free_slob_small链表中寻找slob进行分配;

对于小于1024字节的对象,将从free_slob_medium链表中寻找slob进行分配;

对于大于1024字节的对象,将从free_slob_large链表中寻找slob进行分配;

对于大于PAGE_SIZE的对象,将直接通过伙伴系统分配,不经手Slob分配器;

那么总共只有三个链表,Slob分配器的各类缓存怎么管理自己的空闲对象呢?实际上,所谓的不同类别的缓存都只是伪缓存,因为它们并没有专属自己的内存。当你在Slob分配器中创建一个缓存时,只是声明了该缓存的对象的大小size、对齐值align等,那么当要从该缓存分配对象时,将会根据size定位到相应的链表,寻求分配。因此专用缓存分配对象(kmem_cache_alloc())和普通缓存分配对象(kmalloc())并无太多区别,它们的对象都来源于这三个链表,只不过内核欺骗性的保留了这些接口而已。由此可以想象,struct kmem_cache这个结构在Slob分配器中是很简洁的

 

1.  struct kmem_cache {  

2.      unsigned int size, align; //对象大小,对齐值   

3.      unsigned long flags;      //属性标识   

4.      const char *name;         //缓存名   

5.      void (*ctor)(void *);     //分配对象时的构造函数   

6.  };  

Slob分配器中,一个slob永远都是占用一个页框的大小,所以对于大于PAGE_SIZE的对象,会选择直接通过伙伴系统分配。

Slob分配器将描述slob的变量打包成一个结构,然后和页描述符struct page一起组成一个联合体,这样就可以直接利用页描述符已占有的空间,将页描述符中无关紧要的字段填充为slob的有效描述字段,这样便可以省下一笔内存了!

1.  struct slob_page {  

2.      union {  

3.          struct {  

4.              unsigned long flags;/* 填充用,为了不覆盖page->flags */  

5.              atomic_t _count;      /* 填充用,为了不覆盖page->_count */  

6.              slobidx_t units;      /* slob的空闲单元数 */  

7.              unsigned long pad[2];  

8.              slob_t *free;       /* 指向第一个空闲块 */  

9.              struct list_head list;  /* 用于链入slob全局链表 */  

10.         };  

11.         struct page page;  

12.     };  

13. };  

 

1.  #if PAGE_SIZE <= (32767 * 2)   

2.  typedef s16 slobidx_t;  

3.  #else   

4.  typedef s32 slobidx_t;  

5.  #endif

 

 

对于不同类型的块来说,其管理数据也略有不同:

对于空闲的普通块(占用的单元数大于1),则第一个单元用来填充块的大小,第二个单元用来填充下一个空闲块的偏移

对于小得空闲块(只占用1个单元),则该单元填充下一个空闲对象的偏移的相反数,也就是说是一个负数

对于已经分配出去的块,第一个单元用来填充块的大小

 

 

 

 

 

 

原创粉丝点击