免费注册 查看新帖 |

Chinaunix

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

linux内存屏障的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-10-25 21:18 |只看该作者 |倒序浏览
在网上看到linux的内存屏障的解释:
#define set_mb(var, value) do { var = value; mb(); } while (0)
#define mb() __asm__ __volatile__ ("" : : : "memory")

1)set_mb(),mb(),barrier()函数追踪到底,就是__asm__ __volatile__("":::"memory"),而这行代码就是内存屏障。
2)__asm__用于指示编译器在此插入汇编语句
3)__volatile__用于告诉编译器,严禁将此处的汇编语句与其它的语句重组合优化。即:原原本本按原来的样子处理这这里的汇编。
4)memory强制gcc编译器假设RAM所有内存单元均被汇编指令修改,这样cpu中的registers和cache中已缓存的内存单元中的数据将作废。cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。
5)"":::表示这是个空指令。barrier()不用在此插入一条串行化汇编指令。在后文将讨论什么叫串行化指令。
6)__asm__,__volatile__,memory在前面已经解释


但是"cpu将不得不在需要的时候重新读取内存中的数据。这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存。"
这句话怎么理解呢 ?为什么阻止了cpu又将registers,cache中的数据用于去优化指令就会避免去访问内存?

论坛徽章:
0
2 [报告]
发表于 2009-10-25 22:15 |只看该作者
大概就是CACHE已经有这个数据了~ 不需要从内存读取~

这样编译器就把从内存读取数据的代码给优化掉了~  而实际上因为像DMA这样的操作~ 导致了CACHE和内存中的数据并不一致

内存屏障就是为了防止这样的编译器优化吧~

论坛徽章:
0
3 [报告]
发表于 2009-10-25 22:18 |只看该作者
那怎么做到"避免去访问内存"

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
4 [报告]
发表于 2009-10-25 22:38 |只看该作者
原帖由 nqdgj2007 于 2009-10-25 22:18 发表
那怎么做到"避免去访问内存"


会不会是措辞不清呢?

既然是从网上找到的解释,那就多找一些,对比着理解。

论坛徽章:
0
5 [报告]
发表于 2009-10-25 23:05 |只看该作者
原帖由 superfight 于 2009-10-25 22:15 发表
大概就是CACHE已经有这个数据了~ 不需要从内存读取~

这样编译器就把从内存读取数据的代码给优化掉了~  而实际上因为像DMA这样的操作~ 导致了CACHE和内存中的数据并不一致

内存屏障就是为了防止这样的编译器优化吧~


DMA缓存不是这样来同步的,内核有相应的接口,可以使某一时段内,DMA缓存仅供DMA访问或者仅供CPU访问;或者建立一致性DMA缓存,使得任何时候都废弃这块内存对应的cache。


内存屏障一方面是用于防止编译优化的,另一方面是将cache中的内容刷回内存,使得所有CPU可以立即看到结果

后一个作用中,cache并不是被简单作废的。可以想象,一个CPU刚操作了一块自己的cache,而没有立刻将结果刷会内存中,这时候其他CPU若是要来读这个值了,那么一致性就遭到破坏了,因此会插入一个内存屏障,使得本地CPUcache中的内容被刷回内存中。

论坛徽章:
0
6 [报告]
发表于 2009-10-25 23:17 |只看该作者
楼上说的意思大概是"因此会插入一个内存屏障,使得本地CPUcache中的内容被刷回内存中" 这样的话不是还需要访问内存阿 从内存中读取新的值  那怎么又会"避免去访问内存"

论坛徽章:
0
7 [报告]
发表于 2009-10-26 13:46 |只看该作者
我的看法跟4楼相同,应该是措辞有问题,作者的原话是这样的:“这就阻止了cpu又将registers,cache中的数据用于去优化指令,而避免去访问内存”,真正的意思应该是:“这就阻止了cpu‘去访问cache而不访问内存’”。

论坛徽章:
0
8 [报告]
发表于 2009-10-26 14:51 |只看该作者
这贴应该说的很清楚.
http://linux.chinaunix.net/bbs/v ... p;extra=&page=2
另外又找到个帖子,2年多了,
alb*在最后24楼给出了可能是最好的总结,不得不再次佩服老A.
http://linux.chinaunix.net/bbs/v ... p;extra=&page=3

[ 本帖最后由 epegasus 于 2009-10-27 09:32 编辑 ]

论坛徽章:
0
9 [报告]
发表于 2009-10-27 10:17 |只看该作者
认真看了上面的帖子,还有些不确定的地方.
比如alb说:           
           4.1) 只有一个主体(CPU或DMA控制器)访问内存时,无论如何也不需要barrier;

但是在LKD中文121P
9.10节:
在和硬件交互的一个给定的读时常需要发生在一个给定的写之前.

这个时候是需要内存屏障的,这里的内存屏障不是简单的barrier(),既然barrier()只是防止编译器优话,但不能阻止CPU乱序执行.
那么这个时候需要mb().
按道理说,防止指令乱序,和刷缓存没什么关系,但我怀疑这是处理器设计的策略.如果刷缓存,则处理器大概必然不能存在乱序,反过来则不一定,可以只防止乱序而没必要刷缓存,但是却没有这样一条指令.

论坛徽章:
0
10 [报告]
发表于 2009-10-27 10:38 |只看该作者

回复 #9 epegasus 的帖子

之上这个对于IA32应该没意义,见另一个帖子里的:
intel的是
3. Stores are not reordered with older loads.

再一个问题,我们说多处理器上应该有保证各个cache一致性的方法.那么一致性不应该是需要内存屏障的原因.
lkd2,还是9.10: 在多处理器上可能需要按写数据的顺序读数据.

我再想到一点,比如多个锁变量方式的某种操作,这些读写都是有顺序的.
那么这点才是需要内存屏障的真正原因.

[ 本帖最后由 epegasus 于 2009-10-27 10:54 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP