C++ 是C++;11原子<;T>;可与mmap一起使用?

C++ 是C++;11原子<;T>;可与mmap一起使用?,c++,multithreading,c++11,shared-memory,atomic,C++,Multithreading,C++11,Shared Memory,Atomic,我想添加对Linux嵌入式系统上运行的服务(守护进程)使用的少量参数的网络控制。不需要过程调用,可以以非常自然的方式轮询每个参数。共享内存似乎是一种很好的方法,可以防止网络代码进入守护进程,并限制对一组精心控制的变量的共享访问 因为我不希望部分写入导致从未写入的值的可见性,所以我考虑使用std::atomic和std::atomic。但是,我担心std::atomic的实现方式可能只适用于C++11线程,而不适用于多个进程(可能甚至不适用于OS线程)。具体来说,如果实现使用存储在共享内存块之外的

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

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

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

原子整体专业化和专业化
原子
应具有标准布局。它们都应该有一个普通的默认构造函数和一个普通的析构函数。它们各自应支持聚合初始化语法

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

在我看来,微不足道的默认构造和破坏似乎排除了相关的每对象数据,无论是存储在对象内部、通过指针成员变量还是通过外部映射

但是,我看不到任何东西会将实现排除在使用单个全局互斥/关键部分之外(甚至是全局集合,只要集合元素不与单个原子对象相关联——可以使用缓存关联方案来减少错误冲突)。显然,在使用全局互斥体的实现中,来自多个进程的访问将失败,因为用户将拥有独立的互斥体,并且实际上不会彼此同步

atomic
的实现是否允许执行与进程间共享内存不兼容的操作,或者是否存在其他安全规则


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


在任何情况下,为共享区域中的每个变量保证单个调用
原子_init
似乎都很困难。。。因此,我想我将不得不避开C++11原子类型。

直到C++11,标准没有规定多线程如何共享内存,所以我们使用依赖于实现特定行为的多线程编写程序。该标准仍然没有指定共享内存的进程如何交互,或者如果您愿意,也没有指定仅部分共享内存的线程如何交互。无论您最终做什么,您都将依赖于特定于实现的保证


也就是说,我认为支持进程共享内存的实现将尝试使其线程同步机制(如原子)在进程共享内存中可用于进程同步。至少,我认为很难设计一个std::atomic专门化的无锁实现,它不能在跨进程中正常工作。

我迟到了两个月,但我现在遇到了完全相同的问题,我想我已经找到了某种答案。简短的说法是它应该可以工作,但我不确定我是否会依赖它

以下是我的发现:

  • C++11标准定义了一个新的内存模型,但它没有OS级“进程”的概念,因此任何与多处理相关的东西都是非标准的

  • 然而,本标准第29.4节“无锁财产”(或至少是我的草案,N3337)以本注释结尾:

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

    这听起来很有希望

  • 这个注释似乎来自于,更为明确的是:

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

    因此,似乎是的,所有无锁操作都应该在这种情况下工作

  • 现在,
    std::atomic
    上的操作是原子的,但对于特定的
    类型
    ,它们可能是无锁的,也可能不是无锁的,这取决于平台的功能。我们可以通过调用
    x.is\u lock\u free()
    来检查任何变量
    x

  • 那么,为什么我要写下我不会依赖于此?我找不到任何关于gcc、llvm或任何其他明确说明这一点的文档

作为附录,尽管不清楚他们是否打算包括