C++ 11 atomic <T>可用于mmap吗?

Ben*_*igt 32 c++ multithreading atomic shared-memory c++11

我想添加一个在Linux嵌入式系统上运行的服务(守护进程)使用的一些参数的网络控制.不需要过程调用,每个参数都可以以非常自然的方式进行轮询.共享内存似乎是一种很好的方法,可以将网络代码保留在守护程序之外,并限制对一组精心控制的变量的共享访问.

因为我不希望部分写入导致从未写过的值的可见性,所以我在考虑使用std::atomic<bool>std::atomic<int>.但是,我担心这std::atomic<T>可能会以只适用于C++ 11线程而不是多个进程的方式实现(可能,甚至不包括OS线程).具体来说,如果实现使用存储在共享内存块之外的任何数据结构,则在多进程方案中,这将失败.

我确实看到一些要求,这些要求表明std::atomic不会存在嵌入式锁定对象或指向其他数据的指针:

原子积分专业化和专业化atomic<bool>应具有标准布局.它们每个都有一个普通的默认构造函数和一个普通的析构函数.它们应各自支持聚合初始化语法.

应该有原子类模板的指针部分特化.这些特化应具有标准布局,普通默认构造函数和普通析构函数.它们应各自支持聚合初始化语法.

在我看来,无关紧要的默认构造和破坏是排除关联的每个对象数据,无论是存储在对象内,还是通过指针成员变量,还是通过外部映射.

但是,我认为没有任何东西可以排除使用单个全局互斥/临界区(或者甚至是全局集合)的实现,只要集合元素不与单个原子对象相关联 - 这与缓存关联方案一致可用于减少虚假冲突).显然,使用全局互斥锁的实现对多个进程的访问会失败,因为用户将拥有独立的互斥锁,而不是实际上彼此同步.

atomic<T>允许执行与进程间共享内存不兼容的实现,还是有其他规则使其安全?


我只是注意到,普通的默认构造使对象处于未就绪状态,并且需要调用atomic_init.标准提到了锁的初始化.如果这些存储在对象中(并且动态内存分配似乎不可能,因为析构函数仍然是微不足道的),那么它们将在进程之间共享.但我仍然担心全球互斥的可能性.

在任何情况下,保证atomic_init对共享区域中的每个变量进行单次调用似乎很难......所以我想我将不得不避开C++ 11原子类型.

小智 23

我迟到了两个月,但我现在遇到了同样的问题,我想我找到了某种答案.简短的版本是它应该工作,但我不确定我是否依赖它.

这是我发现的:

  • C++ 11标准定义了一种新的内存模型,但它没有操作系统级"进程"的概念,因此任何与多处理相关的都是非标准的.

  • 但是,标准的第29.4节"无锁属性"(或至少是我的草案,N3337)以本说明结尾:

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

    这听起来很有希望.:)

  • 该说明似乎来自N2427,它更加明确:

    为了通过共享内存促进进程间通信,我们的意图是无锁操作也是无地址的.也就是说,通过两个不同地址在同一存储器位置上的原子操作将以原子方式进行通信.实现不应依赖于任何每个进程的状态.虽然这样的定义超出了标准的范围,但是对我们的意图的明确陈述将使得已经存在的程序类的可移植表达成为可能.

    所以似乎是的,所有无锁操作都应该在这个确切的场景中工作.

  • 现在,操作std::atomic<type>是原子操作,但type根据平台的功能,它们可能或可能不是特定的锁定.我们可以x通过调用来检查任何变量x.is_lock_free().

  • 那么为什么我写这个我不会依赖于此?我找不到任何关于gcc,llvm或任何其他明确的文档的文档.

  • 原子读取-修改-写入操作通过确保该内核是在RMW操作期间唯一具有有效行副本的内核,来阻止其他观察者在RMW中间读取或写入同一高速缓存行。所有现代系统都使用MESI的某种变体来实现高速缓存一致性,其中“修改状态”意味着除“无效”之外,其他任何内核都无法拥有该状态。在x86上,核心采用“缓存锁定”(直到完成RMW后才响应共享缓存行的请求)。在大多数使用LL / SC的服务器上,如果该行未停留在M中,则SC存储条件将中止“事务”。 (2认同)