C++ 对共享内存的原子访问

C++ 对共享内存的原子访问,c++,linux,shared-memory,memory-barriers,stdatomic,C++,Linux,Shared Memory,Memory Barriers,Stdatomic,我在多个进程之间有一个共享内存,这些进程以某种方式对内存进行交互。 例: 我想要的是计数器以原子方式更新/递增。并在该地址上释放内存。 例如,如果我不使用共享内存,它将类似于 std::atomic<int> counter; atomic_store(counter, newvalue, std::memory_order_release); // perform release operation on the affected memory location makin

我在多个进程之间有一个共享内存,这些进程以某种方式对内存进行交互。 例:

我想要的是计数器以原子方式更新/递增。并在该地址上释放内存。 例如,如果我不使用共享内存,它将类似于

std::atomic<int> counter;
atomic_store(counter, newvalue, std::memory_order_release); // perform release     operation on the affected memory location making the write visible to other threads
std::原子计数器;
原子存储(计数器,新值,标准::内存_顺序_释放);//对受影响的内存位置执行释放操作,使写操作对其他线程可见
对于随机内存位置(解释为上面的DataBlock counter>),如何实现这一点。我可以保证地址按照体系结构(x86 linux)的要求对齐

  • 如何使更新原子化?(即原子更新(addr,newvalue))
  • 多核内存同步(即memorysync(addr))-我能看到的唯一方法是使用std::atomic_thread_fence(std::Memory_order_release)-但这将“建立所有原子和轻松原子存储的内存同步顺序”-这对我来说太过分了-我只想同步计数器位置。 感谢你的任何想法

  • 我不能在这里权威地回答,但我可以提供相关信息,可能会有所帮助

  • 互斥锁可以在共享内存中创建和/或跨进程创建。Pthread有一个特殊的创建标志,我不记得是使用共享内存还是共享句柄。linux“futex”可以直接使用共享内存(注意用户地址可能不同,但底层实际地址应该相同)

  • 硬件原子在内存上工作,而不是处理变量。也就是说,你的芯片不会在意哪些程序在修改变量,因此最低级别的原子将自然地进行交叉处理。这同样适用于围栏

  • C++11未能指定跨进程原子。然而,如果它们是无锁的(检查标志),则很难看到编译器如何实现它们,从而使跨进程无法工作。但你会对你的工具链和最终平台充满信心

  • CPU依赖性保证还跟踪实际内存地址,因此只要程序在线程形式下是正确的,它在多进程形式下也应该是正确的(关于可见性)

  • Kerrek是正确的,抽象机器并没有真正提到多个进程。然而,它的同步细节是以这样一种方式编写的,即它们同样适用于进程间,就像它们适用于多线程一样。这与#3有关:编译器很难把它搞砸

  • 简而言之,没有符合标准的方法可以做到这一点。然而,根据标准定义多线程的方式,对于一个高质量的编译器,您可以做出很多假设

    最大的问题是一个原子是否可以简单地分配到共享内存中(新的位置)并工作。显然,只有当它是一个真正的硬件原子时,这才有效。然而,我猜想,使用一个质量编译器/库,C++原子应该在共享内存中找到。
    享受验证行为的乐趣。:)

    由于您使用的是Linux,因此可以在
    计数器的地址上使用
    gcc
    原子内置的
    \uu同步\u获取和添加()。。。根据,这还将实现一个完整的内存限制,而不是释放操作,但因为您实际上需要一个读-修改-写操作,而不仅仅是一个加载(即,增加一个计数器不仅仅是一个加载,而是您必须读取、然后修改,最后写回该值),完整内存围栏将是执行此操作的正确内存顺序的更好选择。

    我正在查看标准草案N4820[atomics.lockfree],它说:

    4[注:无锁的操作也应该是无地址的。也就是说,同一进程上的原子操作 通过两个不同地址的内存位置将进行原子通信 依赖于每个进程的任何状态。此限制允许通过映射到 通过两个进程之间共享的内存进行多次处理。-结束说明]

    因此,如果您的目标是无地址,则先决条件是无锁,这可以通过std::atomic进行检查

    但是,我不确定如何创建
    原子对象。将对象放在共享内存中是否足够好?我还没有找到关于这种用法的任何规范,但我确实在github上看到了这种代码用法

    (编者按:您将指针投射到共享内存,例如

    <代码> AutoP= STATICE-CAST(PTR);与访问任何其他类型的共享内存相同。

    我只是推测,但我的印象是C++编程模型没有“进程”的概念,内存模型没有“共享内存”的概念,所以我怀疑标准本身会做出任何保证。共享内存在很大程度上依赖于平台,因此请查阅平台文档。能否在数据块中放置
    原子
    ?只要
    atomic
    是无锁的(标准显式引用进程之间共享的内存作为这些进程的用例),这应该可以工作。不,你不能只为一个随机地址得到一个原子(见)@Kerrek SB:事实上,这个场景在最终草案的[atomics.lockfree]中提到过。@Grizzly:你是说非规范性注释29.4/3?非常有趣,我不知道。如果共享内存,为什么缓存一致性会有任何不同?我需要的是一种方法,使内存在特定地址的内核之间同步。如果C++支持它,有人知道我可以使用什么ASM指令吗?我在x86上读到,无论如何更新都是原子的,所以我想这已经解决了。std::atomic在线程之间的一个进程内工作,而不是在进程之间工作。一个进程不关心std::原子在另一个进程中的使用。
    \uuuxync\ufetch\u和uadd()
    c
    std::atomic<int> counter;
    atomic_store(counter, newvalue, std::memory_order_release); // perform release     operation on the affected memory location making the write visible to other threads