对共享内存的原子访问

时间:2012-01-06 14:35:46

标签: c++ linux c++11 atomic memory-fences

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

DataBlock {
int counter;
double value1;
double ...    }

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

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
  

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

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

4 个答案:

答案 0 :(得分:9)

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

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

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

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

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

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

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

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

    有趣的验证行为。 :)

答案 1 :(得分:4)

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

答案 2 :(得分:0)

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

4 [Note: Operations that are lock-free should also be address-free. That is, atomic operations on the same
memory location via two different addresses will communicate atomically. The implementation should not
depend on any per-process state. This restriction enables communication by memory that is mapped into a
process more than once and by memory that is shared between two processes. — end note]

因此,如果您要定位为无地址,则前提条件是无锁,可以通过std :: atomic进行检查。

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

答案 3 :(得分:-3)

你可以使用Lock&amp;等待增加计数器的机制。 Boost Library提供了一种锁定和等待机制。点击reference

的此链接