这里我混淆了术语“记忆栅栏”(rust中的“栅栏函数”)。我可以清楚地理解原子方面的内存屏障是什么,但我无法弄清楚什么是内存栅栏。
内存围栏和内存屏障是一样的吗?如果不是,有什么区别,什么时候使用内存栅栏越过内存屏障?
发布于 2020-01-05 11:20:23
这是没有区别的。
“栅栏”和“屏障”在这里的意思是一样的。
发布于 2020-12-07 02:37:23
在这种情况下,“栅栏”是一种记忆屏障。这一区别很重要。出于讨论的目的,我将非正式地区分三种野兽:
(这就是您所问的。)
什么是栅栏
人们用来描述各种原子条件的术语一开始可能有点令人望而生畏,但它们在文档中定义得很好,尽管在撰写本文时有一些遗漏。如果你想了解更多,这里是我建议阅读的文档。
首先是Rust's docs for the Ordering type。这很好地描述了不同Ordering的操作是如何交互的,使用的行话比这一领域的大量参考资料(原子内存排序)要少。但是,在撰写本文时,它对于您的特定问题是误导性的,因为它说的内容如下
此排序仅适用于可以执行存储的操作。
这忽略了fence的存在。
docs for fence用了一些方法来修复它。我想这方面的文档可能需要一些关爱。
我知道,我们不是在写C++,但是Rust从LLVM继承了很多这样的行为,LLVM在这里尝试遵循C++标准。C++文档的行话要高得多,但如果您慢慢阅读,它实际上并不比Rust文档更复杂--只是行话。
什么栅栏不是
我使用内存屏障的最常见原因是在低级代码(如驱动程序)中完成对内存映射I/O的写入。(这是因为我倾向于在堆栈中的低层工作,所以这可能不适用于您的情况。)在这种情况下,您可能正在执行volatile内存访问,并且您想要比fence提供的更强的屏障。
具体地说,fence可以帮助您推断哪些原子内存操作对哪些其他原子内存操作是可见的--它不能帮助您推断某个特定的存储值是否已经完全通过内存层次结构并到达总线的特定级别。例如。对于这样的情况,您需要一种不同的内存屏障。
这些都是在the Linux Kernel's documentation on memory barriers中详细描述的障碍类型。
特别是,您可能会注意到,Ordering和fence的文档没有提到它们如何与volatile内存访问交互,这是因为它们没有。或者至少,它们不能保证--在某些体系结构上,需要生成的指令是相同的(ARM),而在其他情况下,它们不是(PowerPC)。
Rust目前提供了一个可移植的原子屏障(您已经找到了),但是没有提供任何其他类型的内存屏障的可移植版本,比如Linux内核中提供的那些。如果您需要推断(例如) volatile内存访问的完成情况,您将需要不可移植的asm!或最终生成它的函数/宏。
旁白:编译器栅栏
asm("" :::: memory);这既不是原子栅栏,也不是内存屏障:它与Rust的compiler_fence大致相同,因为它阻止编译器在生成的代码中对内存访问进行重新排序。它对机器启动或完成指令的顺序没有影响。
https://stackoverflow.com/questions/59596654
复制相似问题