Linux slub分配和释放分析

Slub内存分配器,是在slab的基础上,进一步优化而来,在内存管理,多处理并发访问上更有优势.

 

这里主要讲解slub分配,释放,调试选项,以及针对slab的优化,源代码基于3.18.22

1. slub框架

 

 

 

   slub是特定大小内存的集合(称为object),每个slub可以包含多个page,代码中用

  struct kmem_cache, struct kmem_cache_node, struct kmem_cache_cpu来实现整个slub

  关系如下:

 

struct kmem_cache {

  struct kmem_cache_cpu __percpu *cpu_slab; /*per cpu数据,分配内存时,可以直接返回object */

unsigned long min_partial; /*每个cache 最小slab数量 */

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. */

int cpu_partial; /* Number of per cpu partial objects to keep around

如果大于这个值,然后就会释放slab到系统中 */

int inuse; /* Offset to metadata */

int align; /* Alignment */

const char *name; /* Name (only for display!) */

struct list_head list; /* List of slab caches */

struct kmem_cache_node *node[MAX_NUMNODES]; /*内存分配 */

};

struct kmem_cache_node {

spinlock_t list_lock; /*访问partial链表锁 */

#ifdef CONFIG_SLUB

unsigned long nr_partial; /*node上的slab数量 */

struct list_head partial; /*所有的slab挂接 */

#endif

};  

struct kmem_cache_cpu {

void **freelist; /* Pointer to next available object */

unsigned long tid; /* Globally unique transaction id:全局标志,用户免锁机制实现 */

struct page *page; /* The freelist from which we are allocating */

struct page *partial; /* Partially allocated frozen slabs list :从node中分配的内存*/

};

 

为什么 kmem_cache_cpu和kmem_cache_node都会挂接内存? 这种做是基于什么目的了?

这种做能够提高内存分配效率,具体在分配一节分析.

2. 内存分配

slub内存分配有五种情况, 效率从高到低.

这里cpu指struct kmem_cache_cpu结构体 node指struct kmem_cache_node

前三种情况都是从percpu上直接分配内存

2. 1. cpu->freelist分配

这种效率最高, 免锁操作,且中断开启

 

2. cpu->page 分配

类似与第一个

cpu->freelist = cpu->page->freelist ;

cpu->page->freelist = NULL ;

 

3. cpu->partial list

percpu的partial 上挂接了多个slab

 

cpu->page = cpu->partial ;

cpu->freelist = cpu->page->freelist ;

cpu->page->freelist = NULL ;

cpu->partial = cpu->page->next ;

免锁操作,禁止本地中断

 

4. node->partial list

如果percpu都分配失败,那么从node上分配 ,这样需要拿spinlock list_lock

1. 获取node->partial第一个page

cpu->page = nodepage

cpu->freelist = nodepage->freelist

nodepage->freelist = NULL

2. 当cpu->partial 总的object小于kmemcache->cpu_partial时

获取node->partial list上的slab 挂接到cpu->partail 直到总的object大于cpu_partail

5. alloc page

 

当上面四种情况都分配失败时,向邻居系统申请page,也即调用page_alloc

 

 

3 内存释放

内存释放分为三种情况

1. free to cput->freelist

2. free to cput->partial list

3. free to node->partial list

再释放object时,还设计到内存回收,也即释放内存到伙伴系统

当cpu partial 的objects > cpu_partial 时,

put page to node partial list

 

当node 上挂接的slab数据nr_partial 大于min_partial 且slab 全空时,

释放内存到伙伴系统

4. slub对并发的优化

this_cpu_cmpxchg_double :避免禁止中断

cmpxchg_double :避免使用锁

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值