【问题标题】:Why is value written by one CPU not seen by the other?为什么一个 CPU 写入的值没有被另一个 CPU 看到?
【发布时间】:2016-08-08 17:27:16
【问题描述】:

对不起,如果这是非常基本的。这是我正在做的事情的简化版本。我正在写一个内核模块。当它运行时,将有两个线程一个两个不同的物理 CPU。我正在使用全局变量在这些线程之间进行某些通信。奇怪的是,有时一个线程的写入不会被另一个线程看到。可能是什么原因?

我怀疑它与内存屏障和缓存同步有关,所以我尝试在写入后使用 smp_wmb() ,但它似乎没有帮助。据我所知,我无法显式控制缓存同步。所以我有点卡住了。

有什么想法吗?

编辑:明确说明是简化版。

【问题讨论】:

  • 可能有很多东西。由于内核模块让我假设 C,你是否声明了变量 volatile?
  • @GabeSechan 是的,我试过了。
  • 遵循其他内核代码使用的模式。此外,除非您正在做一些非常不寻常的事情,否则写入内存屏障应该在写入之前。这个值传达了什么含义?
  • 想要具体答案可以提供code或者code sn-ps
  • 如果你有两个物理 CPU 实现了 NUMA,如果没有适当的处理,这种行为似乎很合理,无论是在其他可能不会发生的架构上(另请注意,这不是不以正确方式做事的借口)。无论如何,NUMA 与否,你应该read this

标签: multithreading linux-kernel memory-barriers smp


【解决方案1】:

首先,你做错了。 CPU 之间的正确同步是非常复杂且非常特定于架构的问题。您应该使用一些现有的内核机制进行线程同步。除非您有一些特定的性能需求,否则只需使用自旋锁。然后,如果需要,您可以阅读更多有关不同同步机制的信息,并找到最适合您的工作负载的一种。

要更直接地回答您的问题 - 您可能会在此处遇到至少两个问题: 1. 编译器对指令重新排序,这通常由编译器屏障处理(即barrier())。 2. CPU 乱序执行和缓存一致性,通常由内存屏障处理。

细节是特定于架构和用例的,但您没有提供我们可以分析的任何代码或架构细节。因此,您可能需要至少使用barrier()smp_wmb()smp_rmb()smp_read_barrier_depends() 中的任何一个。

【讨论】:

    【解决方案2】:

    我认为由于编译器优化,您遇到了问题。

    您是否尝试过使用 volatile ?我认为volatile 适合您的情况。

    volatile 关键字应该用于对来自多个源(进程)的变量执行并发非同步操作的情况。如果变量被声明为 volatile,那么所有进程将始终直接从其内存位置访问该变量,而不是在微处理器的缓存中复制该变量并从那里访问它。

    【讨论】:

    • volatile 限定符通常不会影响变量的值是在缓存中还是在内存中。它通常只影响变量的值是否临时保存在寄存器中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-04
    相关资源
    最近更新 更多