Chinaunix首页 | 论坛 | 博客
  • 博客访问: 314448
  • 博文数量: 72
  • 博客积分: 2580
  • 博客等级: 少校
  • 技术积分: 675
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-07 17:36
文章分类

全部博文(72)

文章存档

2012年(7)

2011年(17)

2010年(46)

2009年(2)

分类: LINUX

2010-07-05 10:16:38

最近看了一下slab的内容。简单写了个结构分析。
大家看看。

这里先感谢一下 hyl 和 Eric Xiao的帮助。


下面是正文:


主要数据结构:

struct kmem_cache_s {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache        *array[NR_CPUS];
        unsigned int                batchcount;
        unsigned int                limit;
/* 2) touched by every alloc & free from the backend */
        struct kmem_list3        lists;
        /* NUMA: kmem_3list_t        *nodelists[MAX_NUMNODES] */
        unsigned int                objsize;
        unsigned int                 flags;        /* constant flags */
        unsigned int                num;        /* # of objs per slab */
        unsigned int                free_limit; /* upper limit of objects in the lists */
        spinlock_t                spinlock;

/* 3) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int                gfporder;

        /* force GFP flags, e.g. GFP_DMA */
        unsigned int                gfpflags;

        size_t                        colour;                /* cache colouring range */
        unsigned int                colour_off;        /* colour offset */
        unsigned int                colour_next;        /* cache colouring */
        kmem_cache_t                *slabp_cache;
        unsigned int                slab_size;
        unsigned int                dflags;                /* dynamic flags */

        /* constructor func */
        void (*ctor)(void *, kmem_cache_t *, unsigned long);

        /* de-constructor func */
        void (*dtor)(void *, kmem_cache_t *, unsigned long);

/* 4) cache creation/removal */
        const char                *name;
        struct list_head        next;

/* 5) statistics */
#if STATS
        unsigned long                num_active;
        unsigned long                num_allocations;
        unsigned long                high_mark;
        unsigned long                grown;
        unsigned long                reaped;
        unsigned long                 errors;
        unsigned long                max_freeable;
        unsigned long                node_allocs;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
        atomic_t                freemiss;
#endif
#if DEBUG
        int                        dbghead;
        int                        reallen;
#endif
};


struct slab {
        struct list_head        list;
        unsigned long                colouroff;
        void                        *s_mem;                /* including colour offset */
        unsigned int                inuse;                /* num of objs active in slab */
        kmem_bufctl_t                free;
};


struct kmem_list3 {
        struct list_head        slabs_partial;        /* partial list first, better asm code */
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long        free_objects;
        int                free_touched;
        unsigned long        next_reap;
        struct array_cache        *shared;
};




cache由 kmem_cache_t(struct kmem_cache_s) 来描述.
slab 由 struct slab 来描述
objec 由 kmem_bufctl_t 来描述



所有的kmem_cache_t 组成链表 cache_chain.该链表由信号量 cache_chain_sem来进行访问保护:
static struct semaphore        cache_chain_sem;
static struct list_head cache_chain;

cache_chain 的第一个高速缓存是 cache_cache. 可以从名字看出来,这个是缓存的缓存.也就是说它存储的是其它缓存的缓存描述符.

高速缓存分为general 和 specific 两种.

对于general的高速缓存,就是cache_cache 和 13个 kmalloc caches.
其中这13个kmalloc caches 的大小呈几何分布:32,64, 128, ... 他们在malloc_sizes表中定义.

specific 的高速缓存是由kmem_cache_create()来创建的.

内核启动的时候,初始化函数kmem_cache_init()来初始化cache_chain. 实际上它创建了general的高速缓存并初始化相应的内容.

整个的cache_chain的情形如下图所示:

cache_chain.gif

一个cache是包含若干个slab,每个slab又包含若干个object. 最终的object才是我们用来存储数据的memory
对于cache, slab, object
这里引用ULK3上的一张图来说明他们之间的关系:

understandlk_0803.jpg

对于每一个cache,其每个slab包含固定数目的连续页框, 由 cachep->gfporder 表示

对于指定的cache, 其object的大小都是固定的,由 cachep->objsize 表示

在cache中,每个slab中的object的个数也是固定的, 由 cachep->num 表示

因而,对于指定的cache,slab的大小也是固定的(sizeof(struct slab) + cachep->num * sizeof(kmem_bufctl_t)), 由 cachep->slab_size 表示

在创建cache的时候(kmem_cache_create()),我们只需要指定object的size,即 cachep->objsize是通过参数来确定的(kmem_cache_create()会根据对齐的要求对齐size)
cachep->gfporder, 一个slab中object的个数,以及slab的大小都是根据kmem_cache_t->objsize 计算出来的.


对于cache描述符kmem_cache_t, slab描述符, 和object之间的结构关系,如下图所示:

kmem_list3_v2.gif

如果需要从一个cache中分配一个object,则通过调用 kmem_cache_alloc()来实现:
kmem_cache_alloc(kmem_cache_t *cachep, unsigned long flag);



上面介绍了高速缓存的基本概念,下面我们将介绍它和memory中的页框是如何关联到一起的.

slab alloctor是通过buddy alloctor来申请页框的.
这在 kmem_cache_alloc() 中,通过调用kmem_getpages();而kmem_getpages()又会相应的调用alloc_pages().

当一个页框被分配给slab之后,page->flag 中的 PG_slab会被置位.同时,该page描述符的lru会分别指向相应的cache和slab, 如下图所示:

page_slab_cache.gif

object 描述符会紧挨着slab描述符来存放,他们的大小为: cachep->slab_size
对于slab描述符,会根据 cachep->objsize 的大小来确定是存放到 slab的内部还是外部.
如果是存放在内部,则会在 kmem_cache_alloc() 分配的页框中存放slab描述符和object描述符
如果是存放在外部,则会根据 cachep->slab_size 的大小, 从13个 kmalloc caches 中选择一个合适的来存放.

object 描述符通常就是一个short int型的值, 对于一个slab,共有 cachep->num 个object 描述符
object描述符存放的是 下一个空闲object的下标, 它只有在object空闲的时候才有意义.
最后一个object描述符的值为 BUFCTL_END,用来标记object的结束.

slab->s_mem 指向第一个slab的地址,
slab->free 指向下一个空闲object的下标,如果没有空闲的object,则为BUFCTL_END

因而,我们可以通过 slab->s_mem + slab->free * cachep->objsize 来找到当前第一个空闲的object的地址
通过(kmem_bufctl_t *)(slab + 1)[slab->free]得到下一个空闲object的下标

                                      
下图是一个简单的示例,来说明slab的结构:   

object.gif

这里再引用ULK3上的一幅图来做补充说明:

understandlk_0805.jpg
最近看了一下slab的内容。简单写了个结构分析。
大家看看。

这里先感谢一下 hyl 和 Eric Xiao的帮助。


下面是正文:


主要数据结构:

struct kmem_cache_s {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache        *array[NR_CPUS];
        unsigned int                batchcount;
        unsigned int                limit;
/* 2) touched by every alloc & free from the backend */
        struct kmem_list3        lists;
        /* NUMA: kmem_3list_t        *nodelists[MAX_NUMNODES] */
        unsigned int                objsize;
        unsigned int                 flags;        /* constant flags */
        unsigned int                num;        /* # of objs per slab */
        unsigned int                free_limit; /* upper limit of objects in the lists */
        spinlock_t                spinlock;

/* 3) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int                gfporder;

        /* force GFP flags, e.g. GFP_DMA */
        unsigned int                gfpflags;

        size_t                        colour;                /* cache colouring range */
        unsigned int                colour_off;        /* colour offset */
        unsigned int                colour_next;        /* cache colouring */
        kmem_cache_t                *slabp_cache;
        unsigned int                slab_size;
        unsigned int                dflags;                /* dynamic flags */

        /* constructor func */
        void (*ctor)(void *, kmem_cache_t *, unsigned long);

        /* de-constructor func */
        void (*dtor)(void *, kmem_cache_t *, unsigned long);

/* 4) cache creation/removal */
        const char                *name;
        struct list_head        next;

/* 5) statistics */
#if STATS
        unsigned long                num_active;
        unsigned long                num_allocations;
        unsigned long                high_mark;
        unsigned long                grown;
        unsigned long                reaped;
        unsigned long                 errors;
        unsigned long                max_freeable;
        unsigned long                node_allocs;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
        atomic_t                freemiss;
#endif
#if DEBUG
        int                        dbghead;
        int                        reallen;
#endif
};


struct slab {
        struct list_head        list;
        unsigned long                colouroff;
        void                        *s_mem;                /* including colour offset */
        unsigned int                inuse;                /* num of objs active in slab */
        kmem_bufctl_t                free;
};


struct kmem_list3 {
        struct list_head        slabs_partial;        /* partial list first, better asm code */
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long        free_objects;
        int                free_touched;
        unsigned long        next_reap;
        struct array_cache        *shared;
};




cache由 kmem_cache_t(struct kmem_cache_s) 来描述.
slab 由 struct slab 来描述
objec 由 kmem_bufctl_t 来描述



所有的kmem_cache_t 组成链表 cache_chain.该链表由信号量 cache_chain_sem来进行访问保护:
static struct semaphore        cache_chain_sem;
static struct list_head cache_chain;

cache_chain 的第一个高速缓存是 cache_cache. 可以从名字看出来,这个是缓存的缓存.也就是说它存储的是其它缓存的缓存描述符.

高速缓存分为general 和 specific 两种.

对于general的高速缓存,就是cache_cache 和 13个 kmalloc caches.
其中这13个kmalloc caches 的大小呈几何分布:32,64, 128, ... 他们在malloc_sizes表中定义.

specific 的高速缓存是由kmem_cache_create()来创建的.

内核启动的时候,初始化函数kmem_cache_init()来初始化cache_chain. 实际上它创建了general的高速缓存并初始化相应的内容.

整个的cache_chain的情形如下图所示:

cache_chain.gif

一个cache是包含若干个slab,每个slab又包含若干个object. 最终的object才是我们用来存储数据的memory
对于cache, slab, object
这里引用ULK3上的一张图来说明他们之间的关系:

understandlk_0803.jpg

对于每一个cache,其每个slab包含固定数目的连续页框, 由 cachep->gfporder 表示

对于指定的cache, 其object的大小都是固定的,由 cachep->objsize 表示

在cache中,每个slab中的object的个数也是固定的, 由 cachep->num 表示

因而,对于指定的cache,slab的大小也是固定的(sizeof(struct slab) + cachep->num * sizeof(kmem_bufctl_t)), 由 cachep->slab_size 表示

在创建cache的时候(kmem_cache_create()),我们只需要指定object的size,即 cachep->objsize是通过参数来确定的(kmem_cache_create()会根据对齐的要求对齐size)
cachep->gfporder, 一个slab中object的个数,以及slab的大小都是根据kmem_cache_t->objsize 计算出来的.


对于cache描述符kmem_cache_t, slab描述符, 和object之间的结构关系,如下图所示:

kmem_list3_v2.gif

如果需要从一个cache中分配一个object,则通过调用 kmem_cache_alloc()来实现:
kmem_cache_alloc(kmem_cache_t *cachep, unsigned long flag);



上面介绍了高速缓存的基本概念,下面我们将介绍它和memory中的页框是如何关联到一起的.

slab alloctor是通过buddy alloctor来申请页框的.
这在 kmem_cache_alloc() 中,通过调用kmem_getpages();而kmem_getpages()又会相应的调用alloc_pages().

当一个页框被分配给slab之后,page->flag 中的 PG_slab会被置位.同时,该page描述符的lru会分别指向相应的cache和slab, 如下图所示:

page_slab_cache.gif

object 描述符会紧挨着slab描述符来存放,他们的大小为: cachep->slab_size
对于slab描述符,会根据 cachep->objsize 的大小来确定是存放到 slab的内部还是外部.
如果是存放在内部,则会在 kmem_cache_alloc() 分配的页框中存放slab描述符和object描述符
如果是存放在外部,则会根据 cachep->slab_size 的大小, 从13个 kmalloc caches 中选择一个合适的来存放.

object 描述符通常就是一个short int型的值, 对于一个slab,共有 cachep->num 个object 描述符
object描述符存放的是 下一个空闲object的下标, 它只有在object空闲的时候才有意义.
最后一个object描述符的值为 BUFCTL_END,用来标记object的结束.

slab->s_mem 指向第一个slab的地址,
slab->free 指向下一个空闲object的下标,如果没有空闲的object,则为BUFCTL_END

因而,我们可以通过 slab->s_mem + slab->free * cachep->objsize 来找到当前第一个空闲的object的地址
通过(kmem_bufctl_t *)(slab + 1)[slab->free]得到下一个空闲object的下标

                                      
下图是一个简单的示例,来说明slab的结构:   

object.gif

这里再引用ULK3上的一幅图来做补充说明:

understandlk_0805.jpg
最近看了一下slab的内容。简单写了个结构分析。
大家看看。

这里先感谢一下 hyl 和 Eric Xiao的帮助。


下面是正文:


主要数据结构:

struct kmem_cache_s {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache        *array[NR_CPUS];
        unsigned int                batchcount;
        unsigned int                limit;
/* 2) touched by every alloc & free from the backend */
        struct kmem_list3        lists;
        /* NUMA: kmem_3list_t        *nodelists[MAX_NUMNODES] */
        unsigned int                objsize;
        unsigned int                 flags;        /* constant flags */
        unsigned int                num;        /* # of objs per slab */
        unsigned int                free_limit; /* upper limit of objects in the lists */
        spinlock_t                spinlock;

/* 3) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int                gfporder;

        /* force GFP flags, e.g. GFP_DMA */
        unsigned int                gfpflags;

        size_t                        colour;                /* cache colouring range */
        unsigned int                colour_off;        /* colour offset */
        unsigned int                colour_next;        /* cache colouring */
        kmem_cache_t                *slabp_cache;
        unsigned int                slab_size;
        unsigned int                dflags;                /* dynamic flags */

        /* constructor func */
        void (*ctor)(void *, kmem_cache_t *, unsigned long);

        /* de-constructor func */
        void (*dtor)(void *, kmem_cache_t *, unsigned long);

/* 4) cache creation/removal */
        const char                *name;
        struct list_head        next;

/* 5) statistics */
#if STATS
        unsigned long                num_active;
        unsigned long                num_allocations;
        unsigned long                high_mark;
        unsigned long                grown;
        unsigned long                reaped;
        unsigned long                 errors;
        unsigned long                max_freeable;
        unsigned long                node_allocs;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
        atomic_t                freemiss;
#endif
#if DEBUG
        int                        dbghead;
        int                        reallen;
#endif
};


struct slab {
        struct list_head        list;
        unsigned long                colouroff;
        void                        *s_mem;                /* including colour offset */
        unsigned int                inuse;                /* num of objs active in slab */
        kmem_bufctl_t                free;
};


struct kmem_list3 {
        struct list_head        slabs_partial;        /* partial list first, better asm code */
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long        free_objects;
        int                free_touched;
        unsigned long        next_reap;
        struct array_cache        *shared;
};




cache由 kmem_cache_t(struct kmem_cache_s) 来描述.
slab 由 struct slab 来描述
objec 由 kmem_bufctl_t 来描述



所有的kmem_cache_t 组成链表 cache_chain.该链表由信号量 cache_chain_sem来进行访问保护:
static struct semaphore        cache_chain_sem;
static struct list_head cache_chain;

cache_chain 的第一个高速缓存是 cache_cache. 可以从名字看出来,这个是缓存的缓存.也就是说它存储的是其它缓存的缓存描述符.

高速缓存分为general 和 specific 两种.

对于general的高速缓存,就是cache_cache 和 13个 kmalloc caches.
其中这13个kmalloc caches 的大小呈几何分布:32,64, 128, ... 他们在malloc_sizes表中定义.

specific 的高速缓存是由kmem_cache_create()来创建的.

内核启动的时候,初始化函数kmem_cache_init()来初始化cache_chain. 实际上它创建了general的高速缓存并初始化相应的内容.

整个的cache_chain的情形如下图所示:

cache_chain.gif

一个cache是包含若干个slab,每个slab又包含若干个object. 最终的object才是我们用来存储数据的memory
对于cache, slab, object
这里引用ULK3上的一张图来说明他们之间的关系:

understandlk_0803.jpg

对于每一个cache,其每个slab包含固定数目的连续页框, 由 cachep->gfporder 表示

对于指定的cache, 其object的大小都是固定的,由 cachep->objsize 表示

在cache中,每个slab中的object的个数也是固定的, 由 cachep->num 表示

因而,对于指定的cache,slab的大小也是固定的(sizeof(struct slab) + cachep->num * sizeof(kmem_bufctl_t)), 由 cachep->slab_size 表示

在创建cache的时候(kmem_cache_create()),我们只需要指定object的size,即 cachep->objsize是通过参数来确定的(kmem_cache_create()会根据对齐的要求对齐size)
cachep->gfporder, 一个slab中object的个数,以及slab的大小都是根据kmem_cache_t->objsize 计算出来的.


对于cache描述符kmem_cache_t, slab描述符, 和object之间的结构关系,如下图所示:

kmem_list3_v2.gif

如果需要从一个cache中分配一个object,则通过调用 kmem_cache_alloc()来实现:
kmem_cache_alloc(kmem_cache_t *cachep, unsigned long flag);



上面介绍了高速缓存的基本概念,下面我们将介绍它和memory中的页框是如何关联到一起的.

slab alloctor是通过buddy alloctor来申请页框的.
这在 kmem_cache_alloc() 中,通过调用kmem_getpages();而kmem_getpages()又会相应的调用alloc_pages().

当一个页框被分配给slab之后,page->flag 中的 PG_slab会被置位.同时,该page描述符的lru会分别指向相应的cache和slab, 如下图所示:

page_slab_cache.gif

object 描述符会紧挨着slab描述符来存放,他们的大小为: cachep->slab_size
对于slab描述符,会根据 cachep->objsize 的大小来确定是存放到 slab的内部还是外部.
如果是存放在内部,则会在 kmem_cache_alloc() 分配的页框中存放slab描述符和object描述符
如果是存放在外部,则会根据 cachep->slab_size 的大小, 从13个 kmalloc caches 中选择一个合适的来存放.

object 描述符通常就是一个short int型的值, 对于一个slab,共有 cachep->num 个object 描述符
object描述符存放的是 下一个空闲object的下标, 它只有在object空闲的时候才有意义.
最后一个object描述符的值为 BUFCTL_END,用来标记object的结束.

slab->s_mem 指向第一个slab的地址,
slab->free 指向下一个空闲object的下标,如果没有空闲的object,则为BUFCTL_END

因而,我们可以通过 slab->s_mem + slab->free * cachep->objsize 来找到当前第一个空闲的object的地址
通过(kmem_bufctl_t *)(slab + 1)[slab->free]得到下一个空闲object的下标

                                      
下图是一个简单的示例,来说明slab的结构:   

object.gif

这里再引用ULK3上的一幅图来做补充说明:

understandlk_0805.jpg
最近看了一下slab的内容。简单写了个结构分析。
大家看看。
这里先感谢一下 hyl 和 Eric Xiao的帮助。

下面是正文:

主要数据结构:
struct kmem_cache_s {
/* 1) per-cpu data, touched during every alloc/free */
        struct array_cache        *array[NR_CPUS];
        unsigned int                batchcount;
        unsigned int                limit;
/* 2) touched by every alloc & free from the backend */
        struct kmem_list3        lists;
        /* NUMA: kmem_3list_t        *nodelists[MAX_NUMNODES] */
        unsigned int                objsize;
        unsigned int                 flags;        /* constant flags */
        unsigned int                num;        /* # of objs per slab */
        unsigned int                free_limit; /* upper limit of objects in the lists */
        spinlock_t                spinlock;
/* 3) cache_grow/shrink */
        /* order of pgs per slab (2^n) */
        unsigned int                gfporder;
        /* force GFP flags, e.g. GFP_DMA */
        unsigned int                gfpflags;
        size_t                        colour;                /* cache colouring range */
        unsigned int                colour_off;        /* colour offset */
        unsigned int                colour_next;        /* cache colouring */
        kmem_cache_t                *slabp_cache;
        unsigned int                slab_size;
        unsigned int                dflags;                /* dynamic flags */
        /* constructor func */
        void (*ctor)(void *, kmem_cache_t *, unsigned long);
        /* de-constructor func */
        void (*dtor)(void *, kmem_cache_t *, unsigned long);
/* 4) cache creation/removal */
        const char                *name;
        struct list_head        next;
/* 5) statistics */
#if STATS
        unsigned long                num_active;
        unsigned long                num_allocations;
        unsigned long                high_mark;
        unsigned long                grown;
        unsigned long                reaped;
        unsigned long                 errors;
        unsigned long                max_freeable;
        unsigned long                node_allocs;
        atomic_t                allochit;
        atomic_t                allocmiss;
        atomic_t                freehit;
        atomic_t                freemiss;
#endif
#if DEBUG
        int                        dbghead;
        int                        reallen;
#endif
};

struct slab {
        struct list_head        list;
        unsigned long                colouroff;
        void                        *s_mem;                /* including colour offset */
        unsigned int                inuse;                /* num of objs active in slab */
        kmem_bufctl_t                free;
};

struct kmem_list3 {
        struct list_head        slabs_partial;        /* partial list first, better asm code */
        struct list_head        slabs_full;
        struct list_head        slabs_free;
        unsigned long        free_objects;
        int                free_touched;
        unsigned long        next_reap;
        struct array_cache        *shared;
};
 

cache由 kmem_cache_t(struct kmem_cache_s) 来描述.
slab 由 struct slab 来描述
objec 由 kmem_bufctl_t 来描述
 
所有的kmem_cache_t 组成链表 cache_chain.该链表由信号量 cache_chain_sem来进行访问保护:
static struct semaphore        cache_chain_sem;
static struct list_head cache_chain;
cache_chain 的第一个高速缓存是 cache_cache. 可以从名字看出来,这个是缓存的缓存.也就是说它存储的是其它缓存的缓存描述符.
高速缓存分为general 和 specific 两种.
对于general的高速缓存,就是cache_cache 和 13个 kmalloc caches.
其中这13个kmalloc caches 的大小呈几何分布:32,64, 128, ... 他们在malloc_sizes表中定义.
specific 的高速缓存是由kmem_cache_create()来创建的.
在内核启动的时候,初始化函数kmem_cache_init()来初始化cache_chain. 实际上它创建了general的高速缓存并初始化相应的内容.
整个的cache_chain的情形如下图所示:
  阿道夫
2008-10-29 11:13
一个cache是包含若干个slab,每个slab又包含若干个object. 最终的object才是我们用来存储数据的memory
对于cache, slab, object
这里引用ULK3上的一张图来说明他们之间的关系:
  下载 (12.01 KB)
2008-10-29 11:13
对于每一个cache,其每个slab包含固定数目的连续页框, 由 cachep->gfporder 表示
对于指定的cache, 其object的大小都是固定的,由 cachep->objsize 表示
在cache中,每个slab中的object的个数也是固定的, 由 cachep->num 表示
因而,对于指定的cache,slab的大小也是固定的(sizeof(struct slab) + cachep->num * sizeof(kmem_bufctl_t)), 由 cachep->slab_size 表示
在创建cache的时候(kmem_cache_create()),我们只需要指定object的size,即 cachep->objsize是通过参数来确定的(kmem_cache_create()会根据对齐的要求对齐size)
cachep->gfporder, 一个slab中object的个数,以及slab的大小都是根据kmem_cache_t->objsize 计算出来的.

对于cache描述符kmem_cache_t, slab描述符, 和object之间的结构关系,如下图所示:
  下载 (12.36 KB)
2008-10-29 11:13
如果需要从一个cache中分配一个object,则通过调用 kmem_cache_alloc()来实现:
kmem_cache_alloc(kmem_cache_t *cachep, unsigned long flag);
 
上面介绍了高速缓存的基本概念,下面我们将介绍它和memory中的页框是如何关联到一起的.
slab alloctor是通过buddy alloctor来申请页框的.
这在 kmem_cache_alloc() 中,通过调用kmem_getpages();而kmem_getpages()又会相应的调用alloc_pages().
当一个页框被分配给slab之后,page->flag 中的 PG_slab会被置位.同时,该page描述符的lru会分别指向相应的cache和slab, 如下图所示:
  下载 (5.41 KB)
2008-10-29 11:13
object 描述符会紧挨着slab描述符来存放,他们的大小为: cachep->slab_size
对于slab描述符,会根据 cachep->objsize 的大小来确定是存放到 slab的内部还是外部.
如果是存放在内部,则会在 kmem_cache_alloc() 分配的页框中存放slab描述符和object描述符
如果是存放在外部,则会根据 cachep->slab_size 的大小, 从13个 kmalloc caches 中选择一个合适的来存放.
object 描述符通常就是一个short int型的值, 对于一个slab,共有 cachep->num 个object 描述符
object描述符存放的是 下一个空闲object的下标, 它只有在object空闲的时候才有意义.
最后一个object描述符的值为 BUFCTL_END,用来标记object的结束.
slab->s_mem 指向第一个slab的地址,
slab->free 指向下一个空闲object的下标,如果没有空闲的object,则为BUFCTL_END
因而,我们可以通过 slab->s_mem + slab->free * cachep->objsize 来找到当前第一个空闲的object的地址
通过(kmem_bufctl_t *)(slab + 1)[slab->free]得到下一个空闲object的下标
                                     
下图是一个简单的示例,来说明slab的结构:  
  下载 (6.32 KB)
2008-10-29 11:13
这里再引用ULK3上的一幅图来做补充说明:
 
阅读(925) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~