资源预览内容
第1页 / 共25页
第2页 / 共25页
第3页 / 共25页
第4页 / 共25页
第5页 / 共25页
第6页 / 共25页
第7页 / 共25页
第8页 / 共25页
第9页 / 共25页
第10页 / 共25页
亲,该文档总共25页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
slab 源码分析源码分析-缓存器的创建缓存器的创建kmem_cache_create() 函数,就是所谓合成缓存器函数。这个函数通常是在内核初始化时进行的,或者在首次加载模块时进行的。struct kmem_cache *kmem_cache_create(const char* name, size_t size, size_t align, unsigned long flags, void (*ctor)(void*, struct kmem_cache *, unsigned long), void (*dtor)(void *, struct kmem_cache *, unsigned long);name 参数定义了缓存器的名称,proc 文件系统(可以 cat /proc/slabinfo 查看)使用它标 识这个缓存。size 参数指定了这个缓存器负责分配的对象大小。align 参数定义了每个对 象必须的对齐。flags 参数指定了为缓存启用的选项。flags 的标志如图:ctor 和 dtor 是构造函数和析构函数,这不用说。在创建缓存器之后,kmem_cache_create() 函数会返回对它的引用。注意这个函数并没有向 缓存器提供任何用来分配对象内存。相反,在试图从缓存器(最初为空)分配对象时,会 通过 cache_alloc_refill() 函数向伙伴系统申请内存。当所有对象都被分配出去后,可以再 次这样做。首先给出该函数的调用机制流程图:首先给出该函数的调用机制流程图:kmem_cache_create()函数:创建缓存器 kmem_cache_zalloc()函数:申请缓存器缓存 _cache_alloc()函数:kmem_cache_alloc 和 kmalloc 申请内存的总接口 _do_cache_alloc()函数:转调函数 _cache_alloc()函数:申请缓存的核心函数 ac=cpu_cache_get()函数,获得本地缓存 if(av-avail),本地缓存足够 取 ac 末尾最热数据,objp=ac-entry-ac-avail 缓存器缓存申请成功 cache_alloc_refill(),重新填充 if(ls-shared),本地共享缓存足够transfer_objects()函数,本地共享缓存转给本地缓存 成功向 ac 中转移了至少一个可用对象 retry:在三链中搜寻可分配对象 三链中有空闲对象 cache_grow()函数,从伙伴系统获取 kmem_getpages()和 alloc_slabmgmt()函数,并执行 retry yes no yes no yes no 下面来看 kmem_cache_create()函数的实现:/* kmem_cache_create - Create a cache.* name: A string which is used in /proc/slabinfo to identify this cache.* size: The size of objects to be created in this cache.* align: The required(必须的的) alignment for the objects. /* flags: SLAB flags* ctor: A constructor for the objects.* dtor: A destructor for the objects (not implemented anymore).* Returns a ptr to the cache on success, NULL on failure. /成功返回 cache 指针,失败返回 空* Cannot be called within a int, but can be interrupted. /不能在中断中调用,但是可以被打 断* The ctor is run when new pages are allocated by the cache* and the dtor is run before the pages are handed back.* name must be valid until the cache is destroyed. This implies that* the module calling this has to destroy the cache before getting unloaded.* The flags are /填充标记* * %SLAB_POISON - Poison(使污染) the slab with a known test pattern (a5a5a5a5) /使用 a5a5a5a5 填充这片未初始化区域 * to catch references to uninitialised memory.* %SLAB_RED_ZONE - Insert Red zones around the allocated memory to check /添加红色 警戒区,检测越界* for buffer overruns.* %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware /物理缓存行对齐,* cacheline. This can be beneficial if youre counting cycles as closely* as davem.*/创建缓存器/* gfporder: 取值 011 遍历直到计算出 cache 的对象数量跳出循环,slab 由 2gfporder 个 页面组成buffer_size: 为当前 cache 中对象经过 cache_line_size 对齐后的大小align: 是 cache_line_size,按照该大小对齐flags: 此处为 0,用于标识内置 slab 还是外置 slableft_over: 输出值,记录 slab 中浪费空间的大小num:输出值,用于记录当前 cache 中允许存在的对象数目*/ struct kmem_cache * kmem_cache_create (const char *name, size_t size, size_t align,unsigned long flags,void (*ctor)(void*, struct kmem_cache *, unsigned long),void (*dtor)(void*, struct kmem_cache *, unsigned long) size_t left_over, slab_size, ralign;struct kmem_cache *cachep = NULL, *pc;/* Sanity checks. these are all serious usage bugs.*/参数检查,名字不能为 NULL,不能在中断中调用本函数(本函数可能会睡眠)/获取长度不得小于 4 字节,即 CPU 字长, 获取长度不得大于最大值(我剖析的这 个版本是 225,有的可能是 222)if (!name | in_interrupt() | (size KMALLOC_MAX_SIZE | dtor) printk(KERN_ERR “%s: Early error in slab %sn“, _FUNCTION_,name);BUG();/* We use cache_chain_mutex to ensure a consistent view of* cpu_online_map as well. Please see cpuup_callback*/mutex_lock(#if 0 /DEBUG 部分被我注释掉了,免得挡点 /一些检查机制,无需关注. #endif /* Check that size is in terms of(依据) words. This is needed to avoid* unaligned accesses for some archs(拱) when redzoning is used, and makes /避免当红 色警戒区被使用时,避免未对齐的访问接触红区* sure any on-slab bufctls are also correctly aligned. /同时确保任何 on-slab 的 bfclt 正确对齐*/ / 为什么 kmem_cache_init 函数已经计算过 size,align 了,这里还要计算?/ 因为这里是用来创建缓存器的,只是借用了 cache_cache,而 kmem_cache_init 函数中初始化的是 cache_cahce 的/ size,align 等成员,所以无关系。/先检查 对象 ! 是不是 32 位对齐,如果不是则进行调整if (size size /* calculate the final buffer alignment: */* 1) arch recommendation: can be overridden for debug */再检查 对象! 要不要求按照缓冲行对齐 if (flags while (size _alignof_(unsigned long long)flags /* 4) Store it.*/align = ralign; /通过上面一大堆计算,算出了 align 值/* Get caches description obj. */按照 cache_cache 的大小分配一个 kmem_cache 新实例,实际上 cache_cache 在内核初 始化完成后就是 kmem_cache 了,为了内核初始化时可使用 kmalloc,所以这里要用 cache_cachecachep = kmem_cache_zalloc( /哈哈,这就是使用 cache_cache/这里会分配一块干净的清零过的内存if (!cachep)goto oops;#if DEBUG. #endif/* Determine if the slab management is on or off slab.* (bootstrapping cannot cope with offslab caches so dont do* it too early on.)*/第一个条件通过 PAGE_SIZE 确定 slab 管理对象的存储方式,内置还是外置。/初始化阶段采用内置式(kmem_cache_init()中创建两个普通高速缓存后就把 slab_early_init 置 0 了if (size = (PAGE_SIZE 3) size = ALIGN(size, align); /从这一步可知,slab 机制先把对象针对及其字长进行对齐, 然后再在此基础上又针对硬件缓冲行进行对齐。/以后所有的对齐都要照这个总的对齐值对齐/计算碎片大小,计算 slab 由几个页面(order)组成,同时计算每个 slab 中有多少个对 象left_over = calculate_slab_order(cachep, size, align, flags); /这次计算的不是 cache_cache
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号