免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1086 | 回复: 0
打印 上一主题 下一主题

Linux内存管理之slab分配器分析(续一) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-03 20:14 |只看该作者 |倒序浏览
在cache这个结构里,有两个很重要的结构:struct array_cache   *array[NR_CPUS]与struct kmem_list3   lists;详细分析一下
struct array_cache {
     unsigned int avail;    //当前空闲对象的位置  
     unsigned int limit;    //允许的空闲对象的最大值
     unsigned int batchcount;    //一次要填充给数组的对象数,或者一次要释放的对象数
     unsigned int touched;       //如果从该组中分配了对象,则把此值置为1
}
struct kmem_list3 {
     struct list_head   slabs_partial;     /*末满的slab链 */
     struct list_head   slabs_full;   /*满的slab链*/
     struct list_head   slabs_free;   /*完全空闲的slab链*/
     unsigned long free_objects;      /*空链的对象数*/
     int      free_touched;
     unsigned long next_reap;
     struct array_cache *shared;      /*全局shar数组。当array[NR_CPUS]满了之后,会将对象释放至此,array[NR_CPUS]请求对象时,会先在这里取得对象 */
}
Slab的数据结构
struct slab {
     struct list_head   list;         /*用来构成链表*/
     unsigned long      colouroff;    /*着色机制,后面会详解*/
     void          *s_mem;       /* 首个对象的起始地址 */
     unsigned int       inuse;        /* slab中的使用对象个数 */
     kmem_bufctl_t      free;         /*slab中的第一个空闲对象的序号*/
};
四:slab中的着色机制
在我们分析详细的代码之前,有必要首先了解一下slab的着色机制。
Slab中引用着色机制是为了提高L1缓冲的效率。我们知道linux是一个兼容性很高的平台,但现在处理器的缓冲区方式多种多样,有的每个处理器有自己的独立缓存。有的很多处理器共享一个缓存。有的除了一级缓存(L1)外还是二级缓存(L2),因此,linux为了更好的兼容处理平台,只优化了一级缓存
为了下面的分析,我们不妨假设一下:假设处理器每根缓存线为32字节,L1大小为16K (可以算出共有512根缓存线),每根缓存线与主存交互的大小也被称为cache line ,在这个例子中cache line是32字节
只有当处理器检测到缓存线冲突时(读或者写失效),才会与主存交互,例如当处理器检测到缓存读失效,会将相应地址所在的32字节读取到缓存。有这里有一点要注意的是,缓存与主存的交互是按照块大小来的,即一次读或者写32字节。而且每条缓存线所读取的地址不是任意的。例如:第0根缓存总线只能读取 0~32 16K ~ 16K+32  32K~32K+32的地址
Slab分配器要求对象按照cache line对齐,我们来看一下,如果没有对齐,会造成什么样的影响:
假设对象为20个字节,一个对象的起始地址是0 位于第0条缓存线。第二个地址的0~9位于第0条缓存线,10~19位于第1条缓存线。可以想象一下,如果要读入第二个对象,就会刷新二个缓存,共64个字节的数据。若是按照cache line对齐,则只要刷新一次高速缓存,只要交互32字节的数据。
当然,如果对象大小太小,我们是以cache line折半来对齐的,这我们在后面的代码中可以看到
讨论完cache line对齐之后,我们再来看看什么叫着色。
假设现在有这样的两个对象A,B A位于0~64于,第0条缓存线。B位于16K之后的64个字节,也是第0条缓存线。我们在上面的分析可以看到,常用的数据结构经常放在结构体的前面。此时就会有高32位的访问频率大大高于低32位的访问频率。假设此时,访问A之后再来访问B。高位访问50次,低位访问10次。
我们来看看这时的情况:
处理器在访问完A后,再访问B的地址,发现B需要缓冲线0,则把缓冲线0的数据写回主存,再读入B的值,访问完B后,发现又要访问A,此时,又把B的值写回主存,再读入A的值 …
按这样计算,共需要和主存交互50*2 + 10*2 = 120次
我们不妨把B后移32字节,这样B的高32位就位于缓存线1 低32位处于缓存线2。这时,访问完A后,访问B只需要把B的数据读科第1,第2缓存线,直接交互就行了。
如果经常有这样的情况发生,就会产生极大的“颠簸”,极度影响系统效率
基于这样的情况。Slab 分器配把每一个slab都错开了,都往后移了一个或者是多个cache line
详细情况可以参考:
[color="#800080"]http://www.linuxforum.net/forum/showflat.php?Cat=&Board=linuxK&Number=83557&page=91&view=collapsed&sb=5&o=all&fpart=1&vc=1
)
在此非常感谢linuxforum的lucian_yao,你的文章给了我极大的帮助 ^_^
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/86301/showart_2063768.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP