C++11原子学:将它们与内存映射的I / O一起使用是否有意义,或者甚至可能

C++11 atomics: does it make sense, or is it even possible, to use them with memory mapped I/O?

本文关键字:是否 有意义 一起 或者 原子学 映射 内存 C++11      更新时间:2023-10-16

据我了解,C volatile和可选的内存围栏内联 asm 已用于在内存映射 I/O 之上实现设备驱动程序。 在 Linux 内核中可以找到几个示例。

如果我们忘记了未捕获异常(如果有的话)的风险,那么用 C++11 原子学替换它们是否有意义? 或者,有可能吗?

一般来说,你可以用原子代替记忆围栏,但不能用volatile代替,除非它与专门用于线程间通信的围栏一起使用。

关于内存映射的I/O,原子学不够的原因是:

  • volatile保证程序中对该变量的所有内存访问都会发生,并且它们完全按照您指定的顺序发生(单个线程)。
  • std::atomic仅保证您的程序的行为就像发生所有这些内存访问一样(根据C++的内存模型,该模型不知道内存映射的I/O),并且 - 取决于指定的内存顺序 - 好像它们按指定的顺序发生。

实际上,这意味着编译器可以例如用一次写入替换对同一(非易失性)原子的连续写入(如果两者之间没有其他同步),读取也是如此。如果不使用读取结果,它甚至可以完全消除读取(编译器可能仍然必须发出内存屏障)。

在更理论的层面上,如果你的编译器可以证明你的程序所做的只是返回 42,那么允许将其转换为单个指令,而与程序在此过程中使用多少线程和原子无关。如果您的程序使用易失性变量,则情况并非如此。

编辑:例如,本文展示了一些可能的(可能是意想不到的)优化,编译器被允许应用于原子循环变量。

据我了解,读取参考文献std::atomic旨在管理对内存的多线程访问(并发等)。但正如我所知,正如你所说,volatile是为内存映射 I/O 和信号处理等而设计的。因此,volatile对原子访问没有影响,如果单独使用,则不能解决多线程访问问题,例如原子。反之亦然 - 原子不提供volatile的功能.

因此,对您的问题的简短回答是否定的。