《Linux内核设计与实现》读书笔记(12)--- 内存管理(2)

时间:2022-10-05 16:56:18

6.slab层

    为了便于数据的频繁分配和回收,Linux内核提供了slab层(也就是所谓的slab分配器)。slab分配器扮演了通用数据结构缓存层的角色。

    slab层把不同的对象划分为所谓高速缓存(cache)组,其中每个高速缓存都存放不同类型的对象。这些高速缓存又被划分为slab,slab由一个或多个物理上连续的页组成。一般情况下,slab也就仅仅由一页组成。每个调整缓存可以由多个slab组成。

    每个slab都包含一些对象成员,这里的对象指的是被缓存的数据结构。每个slab处于三种状态之一:满、部分满或空。每个高速缓存都是用 kmem_cache_s 结构来表示。这个结构包含三个链表 slabs_full,slabs_partial 和 slabs_empty,均存放在 kmem_lists 结构内。这些链表包含高速缓存中的所有slab。slab描述符 struct slab 用来描述每个slab:

struct slab {
    struct list_head list;         /* 满、部分满或空链表 */
    unsigned long colouroff;  /* slab 着色的偏移量   */
    void *s_mem;                  /* 在 slab 中的第一个对象 */
    unsigned int inuse;          /* 已分配的对象数        */
    kmem_bufctl_t tree;         /* 第一个空间对象(如果有的话) */
};

    一个新的高速缓存是通过以下函数创建:

kmem_cache_t *kmem_cache_create(
    const char *name,         /* 存放着高速缓存的名字 */
    size_t size,                    /* 高速缓存中每个元素的大小 */
    size_t align,                   /* 高速缓存内第一个对象的偏移,通常0可以满足要求 */
    unsigned long flags,      /* 控制高速缓存的行为,可以为0,或者标志组合 */
    void (*ctor)( void *, kmem_cache_t *, unsigned long ),   /* 构造函数 */
    void (*dtor)( void *, kmem_cache_t *, unsigned long )); /* 析构函数 */ 

    《Linux内核设计与实现》读书笔记(12)--- 内存管理(2)

    kmem_cache_create 在成功时会返回一个指向所创建高速缓存的指针,否则,返回 NULL。这个函数不能在中断上下文中调用,因为它可能会睡眠。

    要销毁一个高速缓存,则调用:

int kmem_cache_destroy( kmem_cache_t *cachep );

    调用该函数之前必须确保存在以下两个条件:

    1)高速缓存中的所有slab都必须为空。

    2)在调用 kmem_cache_destroy 期间不再访问这个高速缓存,调用者必须确保这种同步。

    该函数成功执行,返回0;否则,返回非0值。

    创建高速缓存之后,就可以通过下列函数从中获取对象:

void *kmem_cache_alloc( kmem_cache_t *cachep, int flags );

    该函数从给定的高速缓存 cachep 中返回一个指向对象的指针,如果高速缓存的所有 slab 中都没有空间的对象,那么 slab层必须通过 kmem_getpages 获取新的页,flags的值传递给 __get_free_pages。应该使用 GFP_KERNEL 或 GFP_ATOMIC。

    释放一个对象,并把它返回给原先的slab,可以使用下面这个函数:

void kmem_cache_free( kmem_cache_t *cachep, void *objp);