linux内存管理之slab数据结构五巨头(3+2)

slab系统实现很复杂,需要静下心来学习的话需要按照如下步骤展开
1:了解其解决问题的场景
2:然后是其原理
3:再次分析其涉及的数据结构的关系
4:后面就是接口和内部实现了。
我们本章主要分析其涉及的数据结构。
slab涉及的数据结构主要有5个。
最重要的3个:
kmem_cache:内存缓冲区描述符,是一个链表,链接不同的kmem_cache
slab:slab描述符,也是一个链表,链接同种类型的slab
kmem_bufctl_t:高速缓存对象描述符,是个数组,链接空闲的slab对象

另外两个
kmem_list3:是kmem_cache和slab的桥梁,其中3代表slab描述符的3种状态链表
array_cache:缓存数组,提升效率

第一个结构体定义

Slab.c (c:\linux\linux-2.6.23\mm)
/*
 * struct kmem_cache
 *
 * manages a cache.
 */

struct kmem_cache {
/* 1) per-cpu data, touched during every alloc/free */
	struct array_cache *array[NR_CPUS];
/* 2) Cache tunables. Protected by cache_chain_mutex */
	unsigned int batchcount;
	unsigned int limit;
	unsigned int shared;

	unsigned int buffer_size;
	u32 reciprocal_buffer_size;
/* 3) touched by every alloc & free from the backend */

	unsigned int flags;		/* constant flags */
	unsigned int num;		/* # of objs per slab */

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

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

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

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

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

/* 6) 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;
	unsigned long node_frees;
	unsigned long node_overflow;
	atomic_t allochit;
	atomic_t allocmiss;
	atomic_t freehit;
	atomic_t freemiss;
#endif
#if DEBUG
	/*
	 * If debugging is enabled, then the allocator can add additional
	 * fields and/or padding to every object. buffer_size contains the total
	 * object size including these internal fields, the following two
	 * variables contain the offset to the user object and its size.
	 */
	int obj_offset;
	int obj_size;
#endif
	/*
	 * We put nodelists[] at the end of kmem_cache, because we want to size
	 * this array to nr_node_ids slots instead of MAX_NUMNODES
	 * (see kmem_cache_init())
	 * We still use [MAX_NUMNODES] and not [1] or [0] because cache_cache
	 * is statically defined, so we reserve the max number of nodes.
	 */
	struct kmem_list3 *nodelists[MAX_NUMNODES];
	/*
	 * Do not add fields after nodelists[]
	 */
};

第二个结构体定义

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;
	unsigned short nodeid;
};

第三个结构体定义
slab->free <------------->结构体数组元素

typedef unsigned int kmem_bufctl_t;
typedef unsigned int kmem_bufctl_t;

void *slab_get_obj(struct kmem_cache *cachep, struct slab *slabp, int nodeid)
{
	void *objp = index_to_obj(cachep, slabp, slabp->free);
	kmem_bufctl_t next;

	slabp->inuse++;
	next = slab_bufctl(slabp)[slabp->free];

	slabp->free = next;

	return objp;
}
void slab_put_obj(struct kmem_cache *cachep, struct slab *slabp, void *objp, int nodeid)
{
	unsigned int objnr = obj_to_index(cachep, slabp, objp);

	slab_bufctl(slabp)[objnr] = slabp->free;
	slabp->free = objnr;
	slabp->inuse--;
}

第四个结构体定义

Slab.c (c:\linux\linux-2.6.23\mm)
/*
 * The slab lists for all objects.
 */
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;
unsigned int free_limit;
unsigned int colour_next;/* Per-node cache coloring */
spinlock_t list_lock;
struct array_cache *shared;/* shared per node */
struct array_cache **alien;/* on other nodes */
unsigned long next_reap;/* updated without locking */
int free_touched;/* updated without locking */
};

第五个结构体定义

struct array_cache {
	unsigned int avail;
	unsigned int limit;
	unsigned int batchcount;
	unsigned int touched;
	spinlock_t lock;
	void *entry[];	/*
			 * Must have this definition in here for the proper
			 * alignment of array_cache. Also simplifies accessing
			 * the entries.
			 */
};

初始化,第一个结构体的建立,整个kmem_cache链表的第一个元素

kmem_cache_init
	=>for (i = 0; i < NUM_INIT_LISTS; i++) { //第四个结构体:初始化kmem_list3
		kmem_list3_init(&initkmem_list3[i]);
		if (i < MAX_NUMNODES)
			cache_cache.nodelists[i] = NULL;
	}
	=>INIT_LIST_HEAD(&cache_chain); //初始化第一个结构体:kmem_cache的各个结构体
	list_add(&cache_cache.next, &cache_chain);
	cache_cache.colour_off = cache_line_size();
	cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
	=>sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name,  //分配空间
					sizes[INDEX_AC].cs_size,
					ARCH_KMALLOC_MINALIGN,
					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
					NULL);
	if (!sizes->cs_cachep) {
			sizes->cs_cachep = kmem_cache_create(names->name,
					sizes->cs_size,
					ARCH_KMALLOC_MINALIGN,
					ARCH_KMALLOC_FLAGS|SLAB_PANIC,
					NULL);
		}
#ifdef CONFIG_ZONE_DMA
		sizes->cs_dmacachep = kmem_cache_create(
					names->name_dma,
					sizes->cs_size,
					ARCH_KMALLOC_MINALIGN,
					ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA|
						SLAB_PANIC,
					NULL);
#endif
	=>struct array_cache *ptr;//初始化第五个结构体

	ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);

	BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache);
	memcpy(ptr, cpu_cache_get(&cache_cache),
		   sizeof(struct arraycache_init));
	/*
	 * Do not assume that spinlocks can be initialized via memcpy:
	 */
	spin_lock_init(&ptr->lock);

	cache_cache.array[smp_processor_id()] = ptr;

	ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT);

	BUG_ON(cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep)
		   != &initarray_generic.cache);
	memcpy(ptr, cpu_cache_get(malloc_sizes[INDEX_AC].cs_cachep),
		   sizeof(struct arraycache_init));
	/*
	 * Do not assume that spinlocks can be initialized via memcpy:
	 */
	spin_lock_init(&ptr->lock);

	malloc_sizes[INDEX_AC].cs_cachep->array[smp_processor_id()] = ptr;
	

后续建立专用高速缓存使用如下函数
kmem_cache_create

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值