Related Knowledge

linux内核相关源代码

kernel heap allocation

http://www.wowotech.net/memory_management/426.html

图解slub

Linux中,伙伴系统(buddy system)是以页为单位管理和分配内存。但现实的需求却以字节为单位。slab分配器专为小内存分配而生。

slubslab中的一种,slob也是slab 中的一种.

slub 数据结构

kmem_cache

现在假如从伙伴系统分配一页内存供slub分配器管理。对于slub分配器来说,就是将这段连续内存平均分成若干大小相等的object(对象)进行管理。可是我们总得知道每一个object的size吧!管理的内存页数也是需要知道的吧!不然怎么知道如何分配呢!因此需要一个数据结构管理。那就是struct kmem_cache。kmem_cache数据结构描述如下:

struct kmem_cache {
        struct kmem_cache_cpu __percpu *cpu_slab;
        /* Used for retriving partial slabs etc */
        slab_flags_t flags;
        unsigned long min_partial;
        int size;             /* The size of an object including meta data */
        int object_size;     /* The size of an object without meta data */
        int offset;           /* Free pointer offset. */
    #ifdef CONFIG_SLUB_CPU_PARTIAL
        int cpu_partial;      /* Number of per cpu partial objects to keep around */
    #endif
        struct kmem_cache_order_objects oo;
        /* Allocation and freeing of slabs */
        struct kmem_cache_order_objects max;
        struct kmem_cache_order_objects min;struct kmem_cache_cpu { 
        void **freelist;    /* Pointer to next available object */
        unsigned long tid;  /* Globally unique transaction id */
        struct page *page;  /* The slab from which we are allocating */
    #ifdef CONFIG_SLUB_CPU_PARTIAL
        struct page *partial;   /* Partially allocated frozen slabs */
    #endif
    };struct kmem_cache_cpu { 
        void **freelist;    /* Pointer to next available object */
        unsigned long tid;  /* Globally unique transaction id */
        struct page *page;  /* The slab from which we are allocating */
    #ifdef CONFIG_SLUB_CPU_PARTIAL
        struct page *partial;   /* Partially allocated frozen slabs */
    #endif
    };
        gfp_t allocflags;    /* gfp flags to use on each alloc */
        int refcount;         /* Refcount for slab cache destroy */
        void (*ctor)(void *);
        int inuse;            /* Offset to metadata */
        int align;            /* Alignment */
        int reserved;         /* Reserved bytes at the end of slabs */
        const char *name;    /* Name (only for display!) */
        struct list_head list;  /* List of slab caches */
        struct kmem_cache_node *node[MAX_NUMNODES];
    };

​ 1) cpu_slab:一个per cpu变量,对于每个cpu来说,相当于一个本地内存缓存池。当分配内存的时候优先从本地cpu分配内存以保证cache的命中率。

​ 2) flags:object分配掩码,例如经常使用的SLAB_HWCACHE_ALIGN标志位,代表创建的kmem_cache管理的object按照硬件cache 对齐,一切都是为了速 度。

​ 3) min_partial:限制struct kmem_cache_node中的partial链表slab的数量。虽说是mini_partial,但是代码的本意告诉我这个变量是kmem_cache_node中partial链表最大slab数量,如果大于这个mini_partial的值,那么多余的slab就会被释放。

​ 4) size:分配的object size

​ 5) object_size:实际的object size,就是创建kmem_cache时候传递进来的参数。和size的关系就是,size是各种地址对齐之后的大小。因此,size要大于等于object_size。

​ 6) offset:slub分配在管理object的时候采用的方法是:既然每个object在没有分配之前不在乎每个object中存储的内容,那么完全可以在每个object中存储下一个object内存首地址,就形成了一个单链表。很巧妙的设计。那么这个地址数据存储在object什么位置呢?offset就是存储下个object地址数据相对于这个object首地址的偏移。

​ 7) cpu_partial:per cpu partial中所有slab的free object的数量的最大值,超过这个值就会将所有的slab转移到kmem_cache_node的partial链表。

​ 8) oo:低16位代表一个slab中所有object的数量(oo & ((1 << 16) - 1)),高16位代表一个slab管理的page数量((2^(oo 16)) pages)。

​ 9) max:看了代码好像就是等于oo。