kernel hacker修炼之道之内存管理-SLUB(SLUB的基本数据结构)

kernel hacker修炼之道之内存管理-SLUB

作者:李万鹏 于北京 borqs

2011.9.17 11:07

本SLUB系列文章从几个方面讨论:

1. SLUB的基本数据结构

2. 创建SLUB高速缓存kmem_cache_create()

3. 销毁SLUB高速缓存kmem_cache_destroy()

4. 创建SLAB块new_slab()

5. 撤销SLAB块free_slab()

6. 分配SLAB对象kmem_cache_alloc()

7. 释放SLAB对象kmem_cache_free()

8. SLUB系统的初始化代码



SLAB系列文档详细讲解了slab的框架源码,但是slab存在众多的不足。

1.复杂的队列管理机制。

2.数据结构过于庞大,浪费空间。

3.着色并不能完全解决cache miss。

4.对NUMA支持,内存回收,性能调优都非常复杂。



SLAB块的内部组织:


下边看一些核心数据结构:

struct kmem_cache { struct kmem_cache_cpu __percpu *cpu_slab; /* Used for retriving partial slabs etc */ unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ int objsize; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ struct kmem_cache_order_objects oo; /* Allocation and freeing of slabs */ struct kmem_cache_order_objects max; struct kmem_cache_order_objects min; 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 */ #ifdef CONFIG_SYSFS struct kobject kobj; /* For sysfs */ #endif #ifdef CONFIG_NUMA /* * Defragmentation by allocating from a remote node. */ int remote_node_defrag_ratio; #endif struct kmem_cache_node *node[MAX_NUMNODES]; }; 每一个cache用一个struct kmem_cache进行描述。size是分配给对象的大小,objsize是对象的实际大小,offset是存放空闲对象指针的偏移。oo成员的高位保存页面的order,低位保存对象的个数。name是缓冲区的名字。struct kmem_cache_node为每个节点创建的slab信息的数据结构。

下边就是一个slab对象的结构:

struct kmem_cache_cpu { void **freelist; /* Pointer to next available object */ #ifdef CONFIG_CMPXCHG_LOCAL unsigned long tid; /* Globally unique transaction id */ #endif struct page *page; /* The slab from which we are allocating */ int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS unsigned stat[NR_SLUB_STAT_ITEMS]; #endif }; struct kmem_cache_cpu就是percpu local slab了,freelist指向一个空闲对象队列的第一个对象。page指向slab的第一个物理页框,顺便说一下,在SLUB中没有slab描述符,而是用slab第一个物理页框的struct page结构,给page结构新增加几个字段,比如:

union { atomic_t _mapcount; /* Count of ptes mapped in mms, * to show when page is mapped * & limit reverse map searches. */ struct { /* SLUB */ u16 inuse; u16 objects; }; }; union { struct { unsigned long private; struct address_space *mapping; }; struct kmem_cache *slab; /* SLUB: Pointer to slab */ struct page *first_page; /* Compound tail pages */ }; union { pgoff_t index; /* Our offset within mapping. */ void *freelist; /* SLUB: freelist req. slab lock */ }; 他们都是union的,所以并不增加struct page结构的大小,也只有是slab第一个物理页框的页描述符的时候这些字段才有效。

struct kmem_cache_node { spinlock_t list_lock; /* Protect partial list and nr_partial */ unsigned long nr_partial; struct list_head partial; #ifdef CONFIG_SLUB_DEBUG atomic_long_t nr_slabs; atomic_long_t total_objects; struct list_head full; #endif }; struct kmem_cache_node是与节点有关的,如果有多个节点就有多个kmem_cache_node,如文档上边的图,partial和full字段分别是slabs_partial slabs_full这两个双向循环链表的头,nr_partial字段是slabs_partial链表上slab的数量。slabs_full链表也只是在调式的时候才打开,这里去掉了slabs_free链表,如果slab变成free了就直接释放掉,这样就不像SLAB那样需要复杂的回收算法了。

下边简单的对SLAB与SLUB进行一下比较:

1.SLUB只有slabs_full与slabs_partial两条链表

2.SLUB去掉了share local list

3.去掉了庞大的SLAB管理对象

4.去掉了着色,因为在SLAB 块比较多的时候着色就不怎么起作用了,反而SLUB中用的cache复用更能解决问题

5.local slab直接取到一个SLAB块而不是cpu local salb指针接管从share local list,再从slab list3,简化了slab管理


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值