slab之基本概念

内核版本: 2.6.11

1. slab描述符

每个slab都有自己的描述符。
定义如下:

 207 struct slab {                                                                                                                                                                                         
 208         struct list_head        list;                                                                    
 209         unsigned long           colouroff;                                                               
 210         void                    *s_mem;         /* including colour offset */   
 211         unsigned int            inuse;          /* num of objs active in slab */
 212         kmem_bufctl_t           free;                                                                    
 213 }; 

2. 对象描述符

每个object也有一个描述符,类型为kmem_bufctl_t,其实是个无符号短整型。作用在下面会介绍。

66 typedef unsigned short kmem_bufctl_t; 

对象
说明:
1)着色的实现

1780 static int cache_grow (kmem_cache_t * cachep, int flags, int nodeid)            
1781 {
....
1809         /* Get colour for the slab, and cal the next value. */                  
1810         offset = cachep->colour_next;                                           
1811         cachep->colour_next++;                                                  
1812         if (cachep->colour_next >= cachep->colour)                              
1813                 cachep->colour_next = 0;                                        
1814         offset *= cachep->colour_off;                                           
1815                                                                                 
1816         spin_unlock(&cachep->spinlock);                                         
1817                                                                                 
1818         if (local_flags & __GFP_WAIT)                                           
1819                 local_irq_enable();                                             
1820                                                                                 
1821         /*                                                                      
1822          * The test for missing atomic flag is performed here, rather than      
1823          * the more obvious place, simply to reduce the critical path length    
1824          * in kmem_cache_alloc(). If a caller is seriously mis-behaving they    
1825          * will eventually be caught here (where it matters).                   
1826          */                                                                     
1827         kmem_flagcheck(cachep, flags);                                          
1828                                                                                 
1829                                                                                 
1830         /* Get mem for the objs. */                                             
1831         if (!(objp = kmem_getpages(cachep, flags, nodeid)))                     
1832                 goto failed;                                                    
1833                                                                                 
1834         /* Get slab management. */                                              
1835         if (!(slabp = alloc_slabmgmt(cachep, objp, offset, local_flags)))       
1836                 goto opps1;  
...
}

在1810行,增加cache->colour_next,然后乘以对齐因子cache->colour_off,得到offset,然后通过alloc_slabmgmt加上着色值。

2)怎么实现object描述符和slab描述符靠在一起?

1678 static struct slab* alloc_slabmgmt (kmem_cache_t *cachep,                       
1679                         void *objp, int colour_off, int local_flags)            
1680 {                                                                               
1681         struct slab *slabp;                                                     
1682                                                                                 
1683         if (OFF_SLAB(cachep)) {                                                 
1684                 /* Slab management obj is off-slab. */                          
1685                 slabp = kmem_cache_alloc(cachep->slabp_cache, local_flags);     
1686                 if (!slabp)                                                     
1687                         return NULL;                                            
1688         } else {                                                                
1689                 slabp = objp+colour_off;                                        
1690                 colour_off += cachep->slab_size;                                
1691         }                                                                       
1692         slabp->inuse = 0;                                                       
1693         slabp->colouroff = colour_off;                                          
1694         slabp->s_mem = objp+colour_off;                                         
1695                                                                                 
1696         return slabp;                                                                                                                                                                                 
1697 } 

在1694行,可以看到slabp->s_mem赋值偏移color_offset,看看colour_off这个偏移量里面有没有object描述符,
在1690行,可以看到colour_off除了包含着色值,还包含cachep->slab_size。跟踪下cachep->slab的赋值。

1186 kmem_cache_t *                                                                  
1187 kmem_cache_create (const char *name, size_t size, size_t align,                 
1188         unsigned long flags, void (*ctor)(void*, kmem_cache_t *, unsigned long),
1189         void (*dtor)(void*, kmem_cache_t *, unsigned long))                     
1190 {  
....
1391         if (flags & CFLGS_OFF_SLAB) {                                                                    
1392                 /* really off slab. No need for manual alignment */             
1393                 slab_size = cachep->num*sizeof(kmem_bufctl_t)+sizeof(struct slab);                                                                                                                    
1394         }
.....
} 

可以看到,slab_size是包含了cachep->num个对象描述符大小和slab描述符大小的和。

3)怎么操作对象描述符和对象描述符的作用?
首先分析下slab_bufctl函数

1699 static inline kmem_bufctl_t *slab_bufctl(struct slab *slabp)                    
1700 {                                                                               
1701         return (kmem_bufctl_t *)(slabp+1);                                      
1702 } 

输入:slab描述符指针
输出:slab紧挨着的对象描述符
分析:slabp+1,刚好是对象描述符开始的地址,然后转换成kmem_bufctl_t结构。

接着分析下,初始化object函数

1704 static void cache_init_objs (kmem_cache_t * cachep,                             
1705                         struct slab * slabp, unsigned long ctor_flags)          
1706 {                                                                               
1707         int i;                                                                                                                                                                                        
1708                                                                                 
1709         for (i = 0; i < cachep->num; i++) {                                     
1710                 void* objp = slabp->s_mem+cachep->objsize*i;                    
1711 #if DEBUG                                                                       
1712                 /* need to poison the objs? */                                  
1713                 if (cachep->flags & SLAB_POISON)                                
1714                         poison_obj(cachep, objp, POISON_FREE);                  
1715                 if (cachep->flags & SLAB_STORE_USER)                            
1716                         *dbg_userword(cachep, objp) = NULL;                     
1717                                                                                 
1718                 if (cachep->flags & SLAB_RED_ZONE) {                            
1719                         *dbg_redzone1(cachep, objp) = RED_INACTIVE;             
1720                         *dbg_redzone2(cachep, objp) = RED_INACTIVE;             
1721                 }                                                               
1722                 /*                                                              
1723                  * Constructors are not allowed to allocate memory from         
1724                  * the same cache which they are a constructor for.             
1725                  * Otherwise, deadlock. They must also be threaded.             
1726                  */                                                             
1727                 if (cachep->ctor && !(cachep->flags & SLAB_POISON))             
1728                         cachep->ctor(objp+obj_dbghead(cachep), cachep, ctor_flags);
1729                                                                                 
1730                 if (cachep->flags & SLAB_RED_ZONE) {                            
1731                         if (*dbg_redzone2(cachep, objp) != RED_INACTIVE)        
1732                                 slab_error(cachep, "constructor overwrote the"  
1733                                                         " end of an object");   
1734                         if (*dbg_redzone1(cachep, objp) != RED_INACTIVE)        
1735                                 slab_error(cachep, "constructor overwrote the"  
1736                                                         " start of an object"); 
1737                 }                                                               
1738                 if ((cachep->objsize % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON)
1739                         kernel_map_pages(virt_to_page(objp), cachep->objsize/PAGE_SIZE, 0);
1740 #else                                                                           
1741                 if (cachep->ctor)                                               
1742                         cachep->ctor(objp, cachep, ctor_flags);                 
1743 #endif                                                                          
1744                 slab_bufctl(slabp)[i] = i+1;                                    
1745         }                                                                       
1746         slab_bufctl(slabp)[i-1] = BUFCTL_END;                                   
1747         slabp->free = 0;                                                        
1748 } 

可以看到slab_bufctl(slabp)[i]是操作第i个对象描述符。可以看出第i个描述符存的是第i+1个object的索引。最后一个描述符对于BUFCTL_END。

用slabp->free=0,指向第0个object的索引,第0个object描述符的值是第1个object的索引,slab最后一个object的描述符的值是BUFCTL_END。

这样在这个slab获取object只需要,从slab中free变量中,取出空闲object的索引,然后把这个object的描述符的值,也就是下一个空闲object的索引赋值给free.

1983 static void* cache_alloc_refill(kmem_cache_t* cachep, int flags)                
1984 {    
......
2032                 while (slabp->inuse < cachep->num && batchcount--) {            
2033                         kmem_bufctl_t next;                                     
2034                         STATS_INC_ALLOCED(cachep);                              
2035                         STATS_INC_ACTIVE(cachep);                               
2036                         STATS_SET_HIGH(cachep);                                 
2037                                                                                 
2038                         /* get obj pointer */                                   
2039                         ac_entry(ac)[ac->avail++] = slabp->s_mem + slabp->free*cachep->objsize;                                                                                                       
2040                                                                                 
2041                         slabp->inuse++;                                         
2042                         next = slab_bufctl(slabp)[slabp->free];                 
2043 #if DEBUG                                                                       
2044                         slab_bufctl(slabp)[slabp->free] = BUFCTL_FREE;          
2045 #endif                                                                          
2046                         slabp->free = next;                                     
2047                 }    
.....
}

在2039行,就是根据slab中的free指向的object赋值给cache_array,然后slab中inuser增加1,把free指向object的描述符的值也就是下一个空闲object索引赋值给slab的free。

总结:
1)slab的free的值是当前可用的object的索引。
2)slab的free对应的object描述符的值是下一个可用object的索引值,这样object的描述符形成一个简单的链表。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值