首页 文章

C“记忆障碍”的例子[重复]

提问于
浏览
8

这个问题在这里已有答案:

我正在阅读关于volatile关键字的这个问题的答案:

https://stackoverflow.com/a/2485177/997112

这个人说:

防止重新排序的解决方案是使用内存屏障,它向编译器和CPU指示在此点上不能重新排序内存访问 . 在易失性变量访问周围放置这些障碍可确保即使非易失性访问也不会在易失性访问中重新排序,从而允许我们编写线程安全的代码 . 但是,内存障碍还可以确保在达到屏障时执行所有挂起的读/写操作,因此它有效地为我们提供了我们自己需要的所有内容,从而使得volatile不必要 . 我们可以完全删除volatile限定符 .

这个“记忆障碍”在C中是如何实现的?

编辑:

Could someone give a simple code example please?

3 回答

  • 6

    在C 11中使用内存障碍是微不足道的:

    std::atomic<int> i;
    

    i 的所有访问都将受到内存障碍的保护 .

  • 6

    这非常依赖于硬件 . 从相当长的Linux内核documentation of memory barrier开始:

    The Linux kernel has eight basic CPU memory barriers:
    
    TYPE                MANDATORY               SMP CONDITIONAL
    ===============     ======================= ===========================
    GENERAL             mb()                    smp_mb()    
    WRITE               wmb()                   smp_wmb()
    READ                rmb()                   smp_rmb()   
    DATA DEPENDENCY     read_barrier_depends()  smp_read_barrier_depends()
    

    我们特别考虑其中一个: smp_mb() . 如果你打开 asm/x86/um/asm/barrier.h ,你会发现当 CONFIG_SMP 被定义时,

    #define smp_mb()    mb()
    

    如果你向上滚动,你可以看到,根据平台,mb有不同的实现:

    // on x86-32
    #define mb()        alternative("lock; addl $0,0(%%esp)", "mfence", X86_FEATURE_XMM2)
    // on other platforms
    #define mb()        asm volatile("mfence" : : : "memory")
    

    有关这两件事之间差异的更多信息已在this thread中讨论过 . 我希望这有帮助 .

  • 3

    通常,存在“内在函数” - 这些是特殊函数,编译器对它们如何操作(特别是它们是内存屏障)有特殊的了解 . 名称因编译器而异(有时也适用于同一编译器的不同体系结构) .

    例如,MSVC使用_ReadBarrierWriteBarrier_ReadWriteBarrier

    在x86中,它会产生一个 lfencesfencemfence 指令 - 分别会产生"load","store"和"all memory operations"障碍 - 换句话说, lfence 将成为内存读取操作的障碍, sfence 将成为"memory write"障碍, mfence 将成为阻止读写操作的障碍 .

相关问题