Welcome 微信登录

首页 / 操作系统 / Linux / Linux内存管理之slab机制(创建slab)

Linux内核中创建slab主要由函数cache_grow()实现,从slab的创建中我们可以完整地看到slab与对象、页面的组织方式。
  1. /* 
  2.  * Grow (by 1) the number of slabs within a cache.  This is called by 
  3.  * kmem_cache_alloc() when there are no active objs left in a cache. 
  4.  */  
  5.  /*使用一个或多个页面创建一个空slab。 
  6. objp:页面虚拟地址,为空表示还未申请内存页,不为空 
  7. ,说明已申请内存页,可直接用来创建slab*/  
  8. static int cache_grow(struct kmem_cache *cachep,  
  9.         gfp_t flags, int nodeid, void *objp)  
  10. {  
  11.     struct slab *slabp;  
  12.     size_t offset;  
  13.     gfp_t local_flags;  
  14.     struct kmem_list3 *l3;  
  15.   
  16.     /* 
  17.      * Be lazy and only check for valid flags here,  keeping it out of the 
  18.      * critical path in kmem_cache_alloc(). 
  19.      */  
  20.     BUG_ON(flags & GFP_SLAB_BUG_MASK);  
  21.     local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);  
  22.   
  23.     /* Take the l3 list lock to change the colour_next on this node */  
  24.     check_irq_off();  
  25.      /* 获得本内存节点的slab三链 */  
  26.     l3 = cachep->nodelists[nodeid];  
  27.     spin_lock(&l3->list_lock);  
  28.   
  29.     /* Get colour for the slab, and cal the next value. */  
  30.     /* 获得本slab的着色区偏移 */  
  31.     offset = l3->colour_next;  
  32.      /* 更新着色区偏移,使不同slab的着色偏移不同 */  
  33.     l3->colour_next++;  
  34.     /* 不能超过着色区的总大小,如果超过了,重置为0。这就是前面分析过的着色循环问题 
  35.     。事实上,如果slab中浪费的空间很少,那么很快就会循环一次。*/  
  36.     if (l3->colour_next >= cachep->colour)  
  37.         l3->colour_next = 0;  
  38.     spin_unlock(&l3->list_lock);  
  39.     /* 将着色单位区间的个数转换为着色区大小 */  
  40.     offset *= cachep->colour_off;  
  41.   
  42.     if (local_flags & __GFP_WAIT)  
  43.         local_irq_enable();  
  44.   
  45.     /* 
  46.      * The test for missing atomic flag is performed here, rather than 
  47.      * the more obvious place, simply to reduce the critical path length 
  48.      * in kmem_cache_alloc(). If a caller is seriously mis-behaving they 
  49.      * will eventually be caught here (where it matters). 
  50.      */  
  51.     kmem_flagcheck(cachep, flags);  
  52.   
  53.     /* 
  54.      * Get mem for the objs.  Attempt to allocate a physical page from 
  55.      * "nodeid". 
  56.      */  
  57.     if (!objp)/* 还未分配页面,从本内存节点分配1<<cachep->gfporder个页面 
  58.     ,objp为slab首页面的虚拟地址 */  
  59.         objp = kmem_getpages(cachep, local_flags, nodeid);  
  60.     if (!objp)  
  61.         goto failed;  
  62.   
  63.     /* Get slab management. */  
  64.      /* 分配slab管理对象 */  
  65.     slabp = alloc_slabmgmt(cachep, objp, offset,  
  66.             local_flags & ~GFP_CONSTRAINT_MASK, nodeid);  
  67.     if (!slabp)  
  68.         goto opps1;  
  69.     /* 设置page到cache、slab的映射 */  
  70.        slab_map_pages(cachep, slabp, objp);  
  71.   
  72.        /* 初始化slab中的对象 */  
  73.     cache_init_objs(cachep, slabp);  
  74.   
  75.     if (local_flags & __GFP_WAIT)  
  76.         local_irq_disable();  
  77.     check_irq_off();  
  78.     spin_lock(&l3->list_lock);  
  79.   
  80.     /* Make slab active. */  
  81.     list_add_tail(&slabp->list, &(l3->slabs_free));  
  82.     /* 更新本cache增长计数 */  
  83.     STATS_INC_GROWN(cachep);  
  84.     /* 更新slab链表中空闲对象计数 */  
  85.     l3->free_objects += cachep->num;  
  86.     spin_unlock(&l3->list_lock);  
  87.     return 1;  
  88. opps1:  
  89.     kmem_freepages(cachep, objp);  
  90. failed:  
  91.     if (local_flags & __GFP_WAIT)  
  92.         local_irq_disable();  
  93.     return 0;  
  94. }  
执行流程:1,从cache结构中获得并计算着色区偏移量;2,从伙伴系统中获得1<<cachep->gfporder个页面用于slab;3,初始化slab中相关变量,如果是外置式slab需要从新申请slab管理区的空间,由函数alloc_slabmgmt()实现。
  1. /*分配slab管理对象*/  
  2. static struct slab *alloc_slabmgmt(struct kmem_cache *cachep, void *objp,  
  3.                    int colour_off, gfp_t local_flags,  
  4.                    int nodeid)  
  5. {  
  6.     struct slab *slabp;  
  7.   
  8.     if (OFF_SLAB(cachep)) {  
  9.         /* Slab management obj is off-slab. */  
  10.         /* 外置式slab。从general slab cache中分配一个管理对象, 
  11.         slabp_cache指向保存有struct slab对象的general slab cache。 
  12.         slab初始化阶段general slab cache可能还未创建,slabp_cache指针为空 
  13.         ,故初始化阶段创建的slab均为内置式slab。*/  
  14.         slabp = kmem_cache_alloc_node(cachep->slabp_cache,  
  15.                           local_flags, nodeid);  
  16.         /* 
  17.          * If the first object in the slab is leaked (it"s allocated 
  18.          * but no one has a reference to it), we want to make sure 
  19.          * kmemleak does not treat the ->s_mem pointer as a reference 
  20.          * to the object. Otherwise we will not report the leak. 
  21.          *//* 对第一个对象做检查 */  
  22.         kmemleak_scan_area(slabp, offsetof(struct slab, list),  
  23.                    sizeofstruct list_head), local_flags);  
  24.         if (!slabp)  
  25.             return NULL;  
  26.     } else {/* 内置式slab。objp为slab首页面的虚拟地址,加上着色偏移 
  27.     ,得到slab管理对象的虚拟地址 */  
  28.         slabp = objp + colour_off;  
  29.         /* 计算slab中第一个对象的页内偏移,slab_size保存slab管理对象的大小 
  30.         ,包含struct slab对象和kmem_bufctl_t数组 */  
  31.         colour_off += cachep->slab_size;  
  32.     } /* 在用(已分配)对象数为0 */  
  33.     slabp->inuse = 0;  
  34.     /* 第一个对象的页内偏移,可见对于内置式slab,colouroff成员不仅包括着色区 
  35.     ,还包括管理对象占用的空间 
  36.     ,外置式slab,colouroff成员只包括着色区。*/  
  37.     slabp->colouroff = colour_off;  
  38.     /* 第一个对象的虚拟地址 */  
  39.     slabp->s_mem = objp + colour_off;  
  40.     /* 内存节点ID */  
  41.     slabp->nodeid = nodeid;  
  42.     /* 第一个空闲对象索引为0,即kmem_bufctl_t数组的第一个元素 */  
  43.     slabp->free = 0;  
  44.     return slabp;  
  45. }  
  • 1
  • 2
  • 下一页
Linux内存管理之slab机制(初始化)Linux内存管理之slab机制(分配对象)相关资讯      Linux内存 
  • Linux内存管理精述  (01月18日)
  • 在 Linux x86-32 模式下分析内存映  (02/08/2015 07:25:25)
  • Linux下如何释放cache内存  (02/02/2015 13:36:34)
  • 在 Linux x86-64 模式下分析内存映  (02/08/2015 07:33:09)
  • Linux系统入门学习:如何检查Linux  (02/06/2015 10:36:00)
  • Linux内存映射  (04/04/2014 13:21:48)
本文评论 查看全部评论 (0)
表情: 姓名: 字数