缥缈峰一座01号

梁二伯的窝

  DonewsBlog  |  Donews首页  |  Donews社区  |  Donews邮箱  |  我的首页  |  联系作者  |  聚合   |  登录
  86篇文章 :: 0篇收藏:: 27篇评论:: 0个Trackbacks

公告

Equality && Free

文章

收藏

相册

存档


正在读取评论……


2085 /**
2086 * kmem_cache_create - 创建一个 cache.
2087 * @name: 此cache在/proc/slabinfo中显示的名字
2088 * @size: 此cache中每个对象的大小
2089 * @align: 对象对齐方式
2090 * @flags: SLAB 标志
2091 * @ctor: 对象构造函数.
2092 * @dtor: 对象析构函数.
2093 *
2094 * 成功返回cache的指针,失败返回NULL.
2095 * 此函数不能在中断中调用,但能被中断.
2096 * @ctor 将在cache建立新页面时候调用
2097 * @dtor 将在页面被回收时候调用.
2098 *
2099 * @name must be valid until the cache is destroyed. This implies that
2100 * the module calling this has to destroy the cache before getting unloaded.
2101 *
2102 * The flags are
2103 *
2104 * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5)
2105 * to catch references to uninitialised memory.
2106 *
2107 * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check
2108 * for buffer overruns.
2109 *
2110 * %SLAB_HWCACHE_ALIGN - 硬件对齐Align the objects in this cache to a hardware
2111 * cacheline. This can be beneficial if you're counting cycles as closely
2112 * as davem.
2113 */
2114 struct kmem_cache *
2115 kmem_cache_create (const char *name, size_t size, size_t align,
2116 unsigned long flags,
2117 void (*ctor)(void*, struct kmem_cache *, unsigned long),
2118 void (*dtor)(void*, struct kmem_cache *, unsigned long))
2119 {
2120 size_t left_over, slab_size, ralign;
2121 struct kmem_cache *cachep = NULL, *pc;
2122
2123     /*
2124      * 参数检查.
2125      */
2126     if (!name || in_interrupt() || (size < BYTES_PER_WORD) ||
2127         (size > (1 << MAX_OBJ_ORDER) * PAGE_SIZE) || (dtor && !ctor)) {
2128         printk(KERN_ERR "%s: Early error in slab %s\n", __FUNCTION__,
2129                 name);
2130         BUG();
2131     }
2132
2133     /*
2134      * We use cache_chain_mutex to ensure a consistent view of
2135      * cpu_online_map as well.  Please see cpuup_callback
2136      */
2137     mutex_lock(&cache_chain_mutex);//互斥假锁
2138//遍历列表,检查此名字cache是否已经建立
2139     list_for_each_entry(pc, &cache_chain, next) {
2140         char tmp;
2141         int res;
2142
2143         /*
2144          * 当一个module卸载后没有销毁其slab cache且不会被复用时候,打印一个警告信息
2147          */
2148         res = probe_kernel_address(pc->name, tmp);
2149         if (res) {
2150             printk("SLAB: cache with size %d has lost its name\n",
2151                    pc->buffer_size);
2152             continue;
2153         }
2154
2155         if (!strcmp(pc->name, name)) {
2156             printk("kmem_cache_create: duplicate cache %s\n", name);
2157             dump_stack();
2158             goto oops;
2159         }
2160     }
2161
2162  //调式部分略去
2185     if (flags & SLAB_DESTROY_BY_RCU)
2186         BUG_ON(dtor);
2187
2188     /*
2189      * Always checks flags, a caller might be expecting debug support which
2190      * isn't available.
2191      */
2192     BUG_ON(flags & ~CREATE_MASK);
2193
2194     /*
2195      * Check that size is in terms of words.  This is needed to avoid
2196      * unaligned accesses for some archs when redzoning is used, and makes
2197      * sure any on-slab bufctl's are also correctly aligned.
2198      */
        //  #define BYTES_PER_WORD      sizeof(void *)
2199     if (size & (BYTES_PER_WORD - 1)) {
2200         size += (BYTES_PER_WORD - 1);
2201         size &= ~(BYTES_PER_WORD - 1);
2202     }
2203
2204     /* 计算buffer的对齐量 */
2205
2206     /* 1) 不同架构对齐对齐方式*/
2207     if (flags & SLAB_HWCACHE_ALIGN) {
2208         /*
2209          * 默认对齐方式: 在各自体系架构代码中定义. 
2210          * 例外:对象很小以至能在一个cacheline中放下几个对象
2212          */
2213         ralign = cache_line_size();//取得具体体系架构cacheline大小
2214         while (size <= ralign / 2)
2215             ralign /= 2;//当对象小于二分之一cacheline的时候计算具体对齐量
2216     } else {
2217         ralign = BYTES_PER_WORD;//在I386上为4BYTE对齐
2218     }
2219
2220     /*
2221      * Redzoning and user store require word alignment. Note this will be
2222      * overridden by architecture or caller mandated alignment if either
2223      * is greater than BYTES_PER_WORD.
2224      */
2225     if (flags & SLAB_RED_ZONE || flags & SLAB_STORE_USER)
2226         ralign = BYTES_PER_WORD;
2227
2228     /* 2) 体系架构对齐 */
2229     if (ralign < ARCH_SLAB_MINALIGN) {
2230         ralign = ARCH_SLAB_MINALIGN;
2231     }
2232     /* 3) 调用者指定对齐 */
2233     if (ralign < align) {
2234         ralign = align;
2235     }
2236     /* 如果需要关掉调试 */
2237     if (ralign > BYTES_PER_WORD)
2238         flags &= ~(SLAB_RED_ZONE | SLAB_STORE_USER);
2242     align = ralign;
2243
2244     /* 分配一个kmem_cache并以0初始化 */
2245     cachep = kmem_cache_zalloc(&cache_cache, GFP_KERNEL);
2246     if (!cachep)
2247         goto oops;
2248
2249 //调式部分略去
2276     /*
2277      * Determine if the slab management is 'on' or 'off' slab.
2278      * (bootstrapping cannot cope with offslab caches so don't do
2279      * it too early on.)
2280      */
2281     if ((size >= (PAGE_SIZE >> 3)) && !slab_early_init)
2282         /*
2283          * 如果比较大,最好把slab与对象分开存储
2285          */
2286         flags |= CFL.GS_OFF_SLAB;
2287
2288     size = ALIGN(size, align);//对齐后对象大小
2289//计算slab需要page数量,slab中对象个数,以及对齐后剩余量
2290     left_over = calculate_slab_order(cachep, size, align, flags);
2291
2292     if (!cachep->num) {
2293         printk("kmem_cache_create: couldn't create cache %s.\n", name);
2294         kmem_cache_free(&cache_cache, cachep);
2295         cachep = NULL;
2296         goto oops;
2297     }
//计算slab数据结构对齐后需要空间大小,对象个数在calculate_slab_order计算出来
2298     slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t)
2299               + sizeof(struct slab), align);
2300
2301     /*
2302      * 如果设置了off-slab, 但是我们有足够空间将slab与对象存放一起,
2303      * 把off-slab改为on-slab一起存放。(空间节省考虑)
2304      */
2305     if (flags & CFL.GS_OFF_SLAB && left_over >= slab_size) {
2306         flags &= ~CFL.GS_OFF_SLAB;
2307         left_over -= slab_size;
2308     }
2309
2310     if (flags & CFL.GS_OFF_SLAB) {
2311         /* 确实独立存放slab结构. 没必要手工对齐(因为在那边是一个对象,早已经对齐)*/
2312         slab_size =
2313             cachep->num * sizeof(kmem_bufctl_t) + sizeof(struct slab);
2314     }
2315
2316     cachep->colour_off = cache_line_size();
2317     // colour_off其实是对齐的最小单位
2318     if (cachep->colour_off < align)
2319         cachep->colour_off = align;
//color是页面中剩余空间除以对齐单位
2320     cachep->colour = left_over / cachep->colour_off;
2321     cachep->slab_size = slab_size;//slab结构的大小(和对象没关系)
2322     cachep->flags = flags;//下面开始就是设置标志位了
2323     cachep->gfpflags = 0;
2324     if (flags & SLAB_CACHE_DMA)//设置DMA标志
2325         cachep->gfpflags |= GFP_DMA;
2326     cachep->buffer_size = size; //对齐后一个对象大小
2327     cachep->reciprocal_buffer_size = reciprocal_value(size);
2328
2329     if (flags & CFL.GS_OFF_SLAB) {
//如果slab结构独立存放,还需要在通用cache中找到对应大小的slab,作为一个对象存入
2330         cachep->slabp_cache = kmem_find_general_cachep(slab_size, 0u);
2331         /*
2332          * This is a possibility for one of the malloc_sizes caches.
2333          * But since we go off slab only for object size greater than
2334          * PAGE_SIZE/8, and malloc_sizes gets created in ascending order,
2335          * this should not happen at all.
2336          * But leave a BUG_ON for some lucky dude.
2337          */
2338         BUG_ON(!cachep->slabp_cache);
2339     }
2340     cachep->ctor = ctor;
2341     cachep->dtor = dtor;
2342     cachep->name = name;
2343//设置一些多处理器相关变量
2344     if (setup_cpu_cache(cachep)) {
2345         __kmem_cache_destroy(cachep);
2346         cachep = NULL;
2347         goto oops;
2348     }
2349
2350     /* cache setup completed, link it into the list */
2351     list_add(&cachep->next, &cache_chain);//加入cache_chain的链表
2352 oops:
2353     if (!cachep && (flags & SLAB_PANIC))
2354         panic("kmem_cache_create(): failed to create slab `%s'\n",
2355               name);
2356     mutex_unlock(&cache_chain_mutex);
2357     return cachep;
2358 }
2359 EXPORT_SYMBOL(kmem_cache_create);

Trackback: http://tb.donews.net/TrackBack.aspx?PostId=1177944


[点击此处收藏本文]  发表于2007年06月20日 11:49 PM




正在读取评论……

发表评论

大名:
网址:
验证码
评论