现在的位置: 首页 > 综合 > 正文

linux slab精细结构

2016年12月04日 ⁄ 综合 ⁄ 共 1503字 ⁄ 字号 评论关闭

1. 数据结构

上面是用visio画的slab缓存的结构示意图,而且对标出了slab结构的成员的含义以及kmem_cache的主要成员的含义。看看如何从slab中获取对象,由上图可以清晰的看到,slab中的对象获取应该是通过free成员和bufctl数组中的索引来取得对象,从索引到对象转换通过s_mem偏移来确定:
static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab,
				 unsigned int idx)
{
	return slab->s_mem + cache->buffer_size * idx;
}
static inline unsigned int obj_to_index(const struct kmem_cache *cache,
					const struct slab *slab, void *obj)
{
	u32 offset = (obj - slab->s_mem);
	return reciprocal_divide(offset, cache->reciprocal_buffer_size);
}

确实slab就是这么获取对象。

下面来看看如何从kmem_cache中分配对象,从kmem_cache分配对象的过程从上面的图以及注释中应该就可以看出的,kmem_cache中的缓存是array成员,这是一个per-cpu数组,如果说slab是对象的二级缓存,那array算是对象的一级缓存,分配对象应该就是先从当前cpu对应的array中取对象,若array中没有对象了,再从slab中取出batchcount个对象来填充array。基本流程应该是这样的,下面看看内核源码是不是这样的,下面这个函数分配对象的后台:
static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags)
{
	void *objp;
	struct array_cache *ac;

	check_irq_off();

	ac = cpu_cache_get(cachep); //从kmem_cache中获得当前cpu的array
	if (likely(ac->avail)) {
		STATS_INC_ALLOCHIT(cachep);
		ac->touched = 1;
		objp = ac->entry[--ac->avail]; //获得对象的指针并且将可以对象个数减1
	} else {
		STATS_INC_ALLOCMISS(cachep);
		objp = cache_alloc_refill(cachep, flags); //没有可用对象,则重新填充array
		/*
		 * the 'ac' may be updated by cache_alloc_refill(),
		 * and kmemleak_erase() requires its correct value.
		 */
		ac = cpu_cache_get(cachep);
	}
	/*
	 * To avoid a false negative, if an object that is in one of the
	 * per-CPU caches is leaked, we need to make sure kmemleak doesn't
	 * treat the array pointers as a reference to the object.
	 */
	if (objp)
		kmemleak_erase(&ac->entry[ac->avail]);
	return objp;
}

注释标出了分配内存的基本步骤,从slab和kmem_cache的两张图中应该就可以明白大部分的。释放对象基本上就是反过来的过程,多检查几个limit标志即可。


抱歉!评论已关闭.