Linux Slob分配器(一)

Slob分配器相较Slab和Slub分配器而言,最大的特点就是简洁,其总共的实现代码大概就600多行,因此其适用于嵌入式系统。不同于Slab和Slub,Slob分配器没有引入本地CPU高速缓存和本地节点的概念。Slob分配器同样使用链表来管理slob,不过总共只存在三个全局partial_free链表,这三个链表是按对象大小来划分的。

相关阅读:
Linux Slob分配器(二)--分配对象
Linux Slob分配器(三)--释放对象

#define SLOB_BREAK1 256    #define SLOB_BREAK2 1024    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分配器中是很简洁的

struct kmem_cache {       unsigned int size, align; //对象大小,对齐值        unsigned long flags;      //属性标识        const char *name;         //缓存名        void (*ctor)(void *);     //分配对象时的构造函数    };  

接下来的一个问题就是Slob分配器是如何描述slob的。在Slob分配器中,一个slob永远都是占用一个页框的大小,所以对于大于PAGE_SIZE的对象,会选择直接通过伙伴系统分配。Slob分配器将所有的slob组织在三个全局链表中,不过,这些slob的描述结构都不需要进行额外的分配。Slob分配器将描述slob的变量打包成一个结构,然后和页描述符struct page一起组成一个联合体,这样就可以直接利用页描述符已占有的空间,将页描述符中无关紧要的字段填充为slob的有效描述字段,这样便可以省下一笔内存了!

struct slob_page {       union {           struct {               unsigned long flags;/* 填充用,为了不覆盖page->flags */               atomic_t _count;      /* 填充用,为了不覆盖page->_count */               slobidx_t units;      /* slob的空闲单元数 */               unsigned long pad[2];               slob_t *free;       /* 指向第一个空闲块 */               struct list_head list;  /* 用于链入slob全局链表 */           };           struct page page;       };   };  

我们可以看到,实际上真正用于slob管理的项只有三个,即units,free和list.

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/pswys.html