对共享内存的原子访问

exc*_*bur 9 c++ linux atomic memory-fences c++11

我在多个进程之间有一个共享内存,以某种方式插入内存.例如:

DataBlock {
int counter;
double value1;
double ...    }
Run Code Online (Sandbox Code Playgroud)

我想要的是计数器以原子方式更新/递增.并且在该地址上发生内存释放.例如,如果我不使用共享内存,那就像是

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
Run Code Online (Sandbox Code Playgroud)

如何为随机存储器位置(解释为DataBlock计数器>上面)实现此目的.我可以保证地址符合架构的要求(x86 linux)

  1. 使更新成为原子 - 如何?(即atomicupdate(addr,newvalue))
  2. 多核的内存同步 - (即memorysync(addr)) - 我唯一能看到的方法是使用std :: atomic_thread_fence(std :: memory_order_release) - 但这将"建立所有原子和放松原子存储的内存同步排序" - 那就是对我来说太过分了 - 我只想让计数器位置同步.欣赏任何想法.

edA*_*a-y 9

我不能在这里回答权限,但我可以提供可能有帮助的相关信息.

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

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

  3. C++ 11无法指定跨进程原子.但是,如果它们是无锁的(检查标志),很难看出编译器如何实现它们,使得跨进程不起作用.但是你会对你的工具链和最终平台充满信心.

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

  5. Kerrek是正确的,抽象机器并没有真正提到多个进程.但是,它的同步细节是以这样的方式编写的,它们同样适用于进程间,就像它们对多线程一样.这与#3有关:编译器很难将其搞砸.

简而言之,没有符合标准的方法来做到这一点.但是,依靠标准定义多线程的方式,您可以为质量编译器做出许多假设.

最大的问题是原子是否可以简单地分配在共享内存(放置新的)和工作中.显然,只有当它是真正的硬件原子时才会起作用.我的猜测是,使用高质量的编译器/库,C++原子应该在共享内存中找到.

玩得开心验证行为.:)


Jas*_*son 6

由于您使用的是 Linux,您可以在地址上使用gccatomic built-in __sync_fetch_and_add()for counter... 根据atomic built-ins 上gcc-documentation,这也将实现完整的内存栅栏,而不是释放操作,但是由于你实际上想要一个读-修改-写操作而不是简单的加载(即增加计数器不仅仅是加载,而是你必须读取,然后修改,最后写回值),全内存栅栏将是一个更好的选择来强制执行此操作的正确内存顺序。