kmem_cache_init用来初始化cache,在初始化阶段使用了全局静态变量cache_cache,这个变量是用来管理所有cache的kmem_cache的, 也就是说,在初始化阶段,将会创建一个slab,用来存放所有cache的kmem_cache,而创建kmem_cache是通过kmem_cache_create来创建的.所有cache的kmem_cache是根据linux/kmem_sizes.h文件中的所有cache来作为标准的,也就是创建8字节,16字节,32字节,64字节,128字节,256字节...所对应的cache.
kmem_cache_init可以分为五个阶段:
第一个阶段:是根据kmem_cache来设置cache_cache的字段值;
第二个阶段:首先是创建arraycache_init对应的高速缓存,同时也是在这个kmem_cache_create的调用过程中,创建了用于保存cache的kmem_cache的slab,并初始化了slab中的各个对象;
第三个阶段:创建kmem_list3对应的高速缓存,在这里要注意的一点是,如果sizeof(arraycache_t)和sizeof(kmem_list3)的大小一样大,那么就不再使用kmem_cache_create来为kmem_list3创建cache了,因为如果两者相等的话,两者就可以使用同一个cache;
第四个阶段:创建并初始化所有的通用cache和dma cache;
第五个阶段:创建两个arraycache_init对象,分别取代cache_cache中的array字段和malloc_sizes[INDEX_AC].cs_cachep->array字段;
第六个阶段:创建两个kmem_list3对象,取代cache_cache中的kmem_list3字段和malloc_sizes[INDEX_AC].cs_cachep->nodelist3字段.如此一来,经过上面的六个阶段后,所有的初始化工作基本完成了;
下面将来详细地解析每个阶段.
第一阶段:根据kmem_cache来设置cache_cache的字段值;此阶段比较简单,这里就不再详细地介绍了.
第二个阶段:首先是创建arraycache_init对应的高速缓存,同时也是在这个kmem_cache_create的调用过程中,创建了用于保存cache的kmem_cache的slab,并初始化了slab中的各个对象
sizes = malloc_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,NULL);
kmem_cache_create()调用kmem_cache_alloc()获得cache的描述符对象.kmem_cache_alloc()的最终实现是函数____cache_alloc(struct kmem_cache *cachep,gfp_t flags)函数,在初始化阶段,____cache_alloc()函数调用cache_alloc_refill来创建slab并最终返回所分配对象的地址.关于cache_alloc_refill()函数的调用的条件是这样的:当slab中没有可用对象时,就会调用cache_alloc_refill函数来创建slab.cache_alloc_refill()的最终实现为cache_grow(),
cache_grow()函数创建slab,并为slab分配空间.对于mem_cache_create的返回值,我们会发现,最终的返回值的实现是函数cache_alloc_refill(),cache_alloc_refill()函数返回的是
array_cache->entry[--ac->avail];,这里我们来解说一下这个返回值.
在函数cache_alloc_refill中,有这样一段代码:
while(slabp->inuse < cachep->num && batchcount --) {
STATS_INC_ALLOCED(cachep);
STATS_INC_ACTIVE(cachep);
STATS_SET_HIGH(cachep);
ac->entry[ac->avail++] = slab_get_obj(cachep,slabp,numa_node_id());
}
这个循环中的最后一行代码就是用来实现对象的分配的最终分配的,这里我们会发现,之前为void *类型的entry指向的是高速缓存中分配好的对象的地址.这样,当在alloc_cache_refill()最后的返回值中,ac->entry[--ac->avail]就是一个kmem_cache对象的指针,这样就成功实现了kmem_cache_create()
的功能;
第三个阶段:创建kmem_list3对应的高速缓存,这个功能的实现是通过调用函数kmalloc(size,flags)来实现的,kmalloc函数将会从size对应的高速缓存中分配一个对象来满足要求,返回的是新分配对象的地址.第一个kmalloc的实现是从arraycache_init对应的高速缓存中分配出来的,kmalloc的最终实现
所调用的函数和kmem_cache_create相同,只是参数不同而已,一个是cache_cache,另外一个是通用cache;
第四个阶段:创建并初始化所有的通用cache和dma cache,这个过程是遍历malloc_sizes中的所有成员为每个成员创建一个cs_cachep,这个过程就是调用kmem_cache_create()来实现的;
第五个阶段:创建两个arraycache_init对象,分别取代cache_cache中的array字段和malloc_sizes[INDEX_AC].cs_cachep->array字段.这个过程也是调用kmalloc来实现的.
第六个阶段:创建两个kmem_list3对象,取代cache_cache中的kmem_list3字段和malloc_sizes[INDEX_AC].cs_cachep->nodelist3字段.
阅读(1812) | 评论(0) | 转发(0) |