免费注册 查看新帖 |

Chinaunix

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

置疑: 我觉得在linux的slub分配器中,一个内存缓存的BUG [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-14 17:03 |只看该作者 |倒序浏览
对于SLUB不熟的同学可以先跳过了,涉及的东西比较细致。
简单来说SLUB的结构是N(CPU数)个kmem_cache_cpu,和一个kmem_cache_node组成。其中kmem_cache_cpu的目的是为了从技术层面上提高CPU命中缓存,以及在同一个页面上不出现一个脏的内存(即不同时被多个CPU持有)。我把这个实现机制手工在WINDOWS下实现了一套,在开启多个kmem_cache_cpu的时候出现了个问题:
1.在释放对象的时候,判断是否是当前kmem_cache_cpu页面所在
2.如果是,则直接插入
3.如果不是,释放到邻居节点

如果是单个kmem_cache_cpu肯定没问题,但是在多个kmem_cache_cpu下,很可能会把其中一个kmem_cache_cpu已经持有的页面释放到邻居节点。举个例子:

假设一个页面地址是0-9,
kmem_cache_cpu1,持有A页面,空闲的情况为A0-A5
kmem_cache_cpu2,持有B页面,
当轮到kmem_cache_cpu2执行的时候,一个A页面的地址A6释放,程序检测到非B页面,则直接释放到邻居节点。那么这个时候A页面已经被切割成两段,并且在公共的邻居节点中,其他的kmem_cache_cpu很容易就取到。这个时候反而是增加了内存的脏度

论坛徽章:
0
2 [报告]
发表于 2011-01-14 19:09 |只看该作者
LZ的意思是这个A页面可能被cache到多个kmem_cache_cpu上面去,然后每个kmem_cache_cpu会cache这个page中的部分object,是吧?
仔细看了一下代码,貌似的确是这样子的……没有发现避免一个page被多个CPU cache的代码。

虽然多个CPU都cache了一个page(slub层面),但是它们cache的只是page中的一部分,并且每个CPU cache的部分互不相交。
不过由于CPU缓存跟object不是完全对齐的,CPU与CPU的缓存的确可能存在一定的交叉。从而导致一个CPU上的object写操作引起另一个CPU的缓存失效(这就是LZ所谓的“脏”吧?),尽管两个CPU使用的object不会交叉。

从这一点来看,确实应该避免一个page被两个CPU cache(slub层面)才对……


另外补充一点,我觉得kmem_cache_cpu这个东西除了提高CPU的缓存命中以外,还有一个很大的作用是在object分配与回收时,减少CPU之间的竞争。

论坛徽章:
0
3 [报告]
发表于 2011-01-15 04:16 |只看该作者
LZ的意思是这个A页面可能被cache到多个kmem_cache_cpu上面去,然后每个kmem_cache_cpu会cache这个page中的部 ...
kouu 发表于 2011-01-14 19:09


看来还是cu水平比csdn水平高。

加锁应该是每个kmem_cache_cpu有了自己的page后,并且访问这个函数的cpu_id一定只是唯一的。这可以保证吗?
比如2个CPU2个线程,执行分配的时候,进入一个函数体,会不会0号线程执行到get_kmem返回cpu_id为0,然后切换到1好2线程也get_kmem,这时候cpu_id还有可能是0?

论坛徽章:
0
4 [报告]
发表于 2011-01-15 23:00 |只看该作者
加锁应该是每个kmem_cache_cpu有了自己的page后,并且访问这个函数的cpu_id一定只是唯一的。这可以保证吗?
比如2个CPU2个线程,执行分配的时候,进入一个函数体,会不会0号线程执行到get_kmem返回cpu_id为0,然后切换到1好2线程也get_kmem,这时候cpu_id还有可能是0?


可以看到,在slab_alloc函数里面,如果属于当前CPU的kmem_cache_cpu的freelist不为空,那么在这个list里面取object的时候是没有上锁的。

那么,如何避免两个线程因为内核抢占而交叉执行的情况呢(就是你所说的这种情况)?
在slab_alloc里面会有local_irq_save操作,禁止了本地中断。这样也就避免了当前CPU上的内核抢占。

论坛徽章:
0
5 [报告]
发表于 2011-01-16 04:08 |只看该作者
可以看到,在slab_alloc函数里面,如果属于当前CPU的kmem_cache_cpu的freelist不为空,那么在这个list里 ...
kouu 发表于 2011-01-15 23:00



    也就是说,这类东西必须系统底层去实现才能够发挥最大的效率。或者,因为现在硬件发展的规格不同,操作系统也势必可以放出一些接口。

论坛徽章:
0
6 [报告]
发表于 2011-07-17 09:13 |只看该作者
本帖最后由 lin_style 于 2011-07-17 15:17 编辑

回来看看

论坛徽章:
16
2015亚冠之吉达阿赫利
日期:2015-08-17 11:21:462015年迎新春徽章
日期:2015-03-04 09:58:11酉鸡
日期:2014-12-07 09:06:19水瓶座
日期:2014-11-04 14:23:29天秤座
日期:2014-03-02 08:57:52双鱼座
日期:2014-02-22 13:07:56午马
日期:2014-02-14 11:08:18双鱼座
日期:2014-02-13 11:09:37卯兔
日期:2014-02-06 15:10:34子鼠
日期:2014-01-20 14:48:19戌狗
日期:2013-12-19 09:37:46射手座
日期:2013-12-19 09:33:47
7 [报告]
发表于 2011-09-14 15:39 |只看该作者
回复 4# kouu


    在您baidu的博客中看到您写的《linux slub分配器浅析》,有这么一句:“page结构不仅代表了内存,结构里面还有一些union变量用来记录其对应内存的对象分配情况(仅当page被加入到SLUB分配器后有效,其他情况下这些变量有另外的解释)。”这里的“仅当page被加入到SLUB分配器后有效,其他情况下这些变量有另外的解释”是怎么看出来的阿?

论坛徽章:
0
8 [报告]
发表于 2011-09-20 23:12 |只看该作者
又回想起这个问题...... 属于同一个page下的object, 可能被cache到不同CPU的kmem_cache_cpu.
现在想来, 这样貌似也是合理的.

首先, 初始状态下, page加入到slub之后, 属于该page的object都是空闲的, 都存在于page->freelist中;
然后, 这个page可能被某个CPU的kmem_cache_cpu所cache, 假设是CPU-0, 那么这个kmem_cache_cpu将得到属于该page的所有object. page->freelist将为空;
接下来, 这个page的一部分object可能在这个CPU-0上被分配出去;
再接着, 可能由于NUMA的node id不匹配, 这个page被deactivate, 脱离了CPU-0. 这时page->freelist将保存着那些未被分配出去的object(其他的object已经在CPU-0上被分配出去了);

这时, 属于page的一部分object正在CPU-0上被使用着, 另一部分object存在于page->freelist中.
那么, 现在就有两个选择:
1, 这个page不放回到partial list, 阻止其他CPU使用这个page;
2, 将这个page放回partial list, 允许其他CPU使用这个page;

对于第一种做法, 可以避免属于同一个page的object被cache到不同CPU. 但是这个page必须等到CPU-0再次cache它以后才能被继续使用; 或者等待CPU-0所使用的属于这个page的object都全部释放, 然后这个page才能被放回partial list或者直接被释放掉.
这样一来, 一个page尽管有空闲的object, 却可能在一定时间内处于不可用状态(极端情况是永远不可用). 这样实现的系统似乎不太可控...

而现在的slub选择了第二种做法, 将page放回partial list. 于是page马上就能被其他CPU使用起来. 那么也就不得不面临属于同一个page的object被cache到不同CPU的问题. 这也是没办法的事情...

论坛徽章:
0
9 [报告]
发表于 2011-09-21 05:50 |只看该作者
回复 8# kouu

觉得楼上还忘了一点。
   
再接着, 可能由于NUMA的node id不匹配,
回复 8# kouu
    如果没有配置CONFIG_NUMA,这个条件不会被满足。

另外,当CPU2 free object的时候(object属于pageXXX), 而pageXXX恰好被CPU1使用,那么object是直接被挂接到page->freelist.
(这前后会用localirq和spinlock保护)。
我看的是3.0的代码,在slab_free和__slab_free里。

论坛徽章:
0
10 [报告]
发表于 2011-09-21 06:07 |只看该作者
回复 9# seekhunter


    当CPU2 free object的时候(object属于pageXXX), 而pageXXX恰好不被被CPU2使用(可能被cpu1使用,也可能没有cpu使用),那么object是直接被挂接到page->freelist.
(这前后会用localirq和spinlock保护)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP