Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
是不是;易挥发;在多核系统的可移植C代码中保证什么?_C_Multithreading_Thread Safety_Volatile_Portability - Fatal编程技术网

是不是;易挥发;在多核系统的可移植C代码中保证什么?

是不是;易挥发;在多核系统的可移植C代码中保证什么?,c,multithreading,thread-safety,volatile,portability,C,Multithreading,Thread Safety,Volatile,Portability,在看了a之后,我得到的印象是,对于C中的“volatile”关键字的确切含义没有广泛的一致意见。 即使是标准本身似乎也不够清晰,无法让每个人都同意 除其他问题外: 它似乎提供了不同的保证,这取决于您的硬件和编译器 它影响编译器优化,但不影响硬件优化,因此,对于自行进行运行时优化的高级处理器,甚至不清楚编译器是否可以阻止任何您想要阻止的优化。(有些编译器确实会生成指令来阻止某些系统上的某些硬件优化,但这似乎没有以任何方式标准化。) 总结一下这个问题,(在读了很多之后)“volatile”似乎保证了

在看了a之后,我得到的印象是,对于C中的“volatile”关键字的确切含义没有广泛的一致意见。

即使是标准本身似乎也不够清晰,无法让每个人都同意

除其他问题外:

  • 它似乎提供了不同的保证,这取决于您的硬件和编译器
  • 它影响编译器优化,但不影响硬件优化,因此,对于自行进行运行时优化的高级处理器,甚至不清楚编译器是否可以阻止任何您想要阻止的优化。(有些编译器确实会生成指令来阻止某些系统上的某些硬件优化,但这似乎没有以任何方式标准化。)
  • 总结一下这个问题,(在读了很多之后)“volatile”似乎保证了这样一种情况:值不仅从寄存器读取/写入,而且至少要从内核的一级缓存读取/写入,读取/写入的顺序与代码中的读取/写入顺序相同。但这似乎毫无用处,因为在同一个线程中,从寄存器读/写寄存器已经足够了,而与一级缓存的协调并不能保证与其他线程的协调。我无法想象什么时候仅仅与一级缓存同步才是重要的

    使用1
    volatile的唯一广泛使用似乎是用于旧的或嵌入式系统,其中某些内存位置是硬件映射到I/O功能的,例如内存中控制(直接,在硬件中)灯的位,或者内存中告诉您键盘键是否按下的位(因为它由硬件直接连接到钥匙)

    似乎在目标包括多核系统的可移植代码中不会出现“使用1”。

    使用2
    与“使用1”没有太大区别的是,中断处理程序可以在任何时候读取或写入内存(它可以控制灯或存储来自键的信息)。但是,对于这一点,我们已经遇到了一个问题,即根据系统的不同,带和“volatile”的中断处理程序不能保证所有系统上的缓存一致性

    因此,“使用2”似乎超出了“volatile”所能提供的功能。

    使用3
    我看到的另一个无可争议的用途是防止通过指向同一内存的不同变量对访问进行错误优化,编译器没有意识到这是同一内存。但这可能是无可争议的,因为人们没有谈论它——我只看到一次提到它。我认为C标准已经认识到了这一点“不同”指针(如指向函数的不同参数)可能指向同一项或附近的项,并且已经指定编译器必须生成即使在这种情况下也能工作的代码。但是,我无法在最新(500页!)标准中快速找到此主题

    所以“使用3”可能根本不存在

    因此,我的问题是:

    在多核系统的可移植C代码中,“volatile”能保证任何东西吗?


    编辑--更新 浏览后,看起来答案至少是非常有限的“是”:
    1.该标准反复规定了对特定类型“volatile sig_atomic__t”的特殊处理。然而,该标准还指出,在多线程程序中使用信号函数会导致未定义的行为。因此,该用例似乎仅限于单线程程序与其信号处理程序之间的通信。
    2.本标准还规定了与setjmp/longjmp相关的“volatile”的明确含义。(其他和中给出了重要的示例代码。)

    因此,更确切的问题是:
    除了(1)允许单线程程序从其信号处理程序接收信息,或(2)允许setjmp代码查看setjmp和longjmp之间修改的变量外,“volatile”是否能保证多核系统的可移植C代码中的任何内容?

    这仍然是一个肯定/否定的问题


    如果“是”,如果你能展示一个没有bug的可移植代码的例子,如果省略了“volatile”,它就会变成bug。如果“no”,那么我想编译器可以忽略“volatile”“除了这两个非常具体的案例外,对于多核目标而言。

    我不是专家,但cppreference.com在我看来有一些不错的东西。这里是它的要点:

    通过左值表达式进行的每次访问(读和写) 挥发性合格类型被认为是可观察到的副作用 优化和测试的目的严格按照 抽象机器的规则(即,所有写入都在 在下一个序列点之前的某个时间)。这意味着 单线程执行时,无法优化易失性访问 或者相对于另一个分离的可见副作用重新排序 由一个序列点从易失性访问

    它还提供了一些用途:

    挥发性有机物的用途

    1) 静态易失性对象模型内存映射I/O端口和静态 const volatile objects为内存映射的输入端口建模,例如 实时时钟

    2) sig_atomic_t类型的静态易失性对象用于 与信号处理器的通信

    3) 对于包含 setjmp宏的调用是唯一保证的局部变量 在longjmp返回后保留其值

    4) 此外,volatile变量可用于禁用某些 优化形式,例如禁用死区消除或 微基准的恒定折叠

    当然,它提到了
    volatile
    对于线程同步没有用处:<
    volatile int x;
    volatile int y;
    z = x;
    z = y;