Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从shm#U open()和#x2B;mmap()_C++_C_Linux_Posix_Shared Memory - Fatal编程技术网

C++ 从shm#U open()和#x2B;mmap()

C++ 从shm#U open()和#x2B;mmap(),c++,c,linux,posix,shared-memory,C++,C,Linux,Posix,Shared Memory,假设我在CentOS 7 x86_64+GCC 7上 我想在共享内存中创建一个ringbuffer 如果我有两个进程Producer和Consumer,它们都共享一个命名的共享内存,该内存是通过shm_open()+mmap()创建/访问的 如果制作人写了如下内容: struct Data { uint64_t length; char data[100]; } 随机访问共享内存,并且使用者不断轮询共享内存以进行读取。我是否会遇到某种同步问题,即虽然看到了成员长度,但成员数据仍在编写过程中?如

假设我在CentOS 7 x86_64+GCC 7上

我想在共享内存中创建一个ringbuffer

如果我有两个进程Producer和Consumer,它们都共享一个命名的共享内存,该内存是通过shm_open()+mmap()创建/访问的

如果制作人写了如下内容:

struct Data {
uint64_t length;
char data[100];
}
随机访问共享内存,并且使用者不断轮询共享内存以进行读取。我是否会遇到某种同步问题,即虽然看到了成员长度,但成员数据仍在编写过程中?如果是,避免问题的最有效方法是什么

我看到这个帖子:

但我想更深入、更低级地了解两个进程之间高效同步需要什么


提前谢谢

是的,您最终会遇到数据竞争,不仅在写入
数据之前写入和读取
length
,而且这些成员的一部分将在读取过程中被写入

虽然无锁是新的趋势,但我建议您选择一个更简单的工具作为第一个IPC同步作业:信号量。在linux上,以下手册页将非常有用:

其思想是让两个进程都向另一个进程发出信号,该进程当前正在读取或写入共享内存段。使用信号量,您可以编写进程间互斥:

Producer:
while true:
    (opt) create resource
    lock semaphore (sem_wait)
    copy resource to shm
    unlock semaphore (sem_post)

Consumer:
while true:
    lock semaphore (sem_wait)
    copy resource to local memory
        or crunch resource
    unlock semaphore (sem_post)

例如,如果生产者在消费者呼叫
sem\u wait
时写入shm,消费者将阻止,直到生产者呼叫
sem\u post
,但,您无法保证生产者不会进行另一个循环,在消费者被唤醒之前连续写入两次。您必须构建一种机制,以确保生产者和消费者能够交替工作。

为了避免这种情况,您需要使结构
std::atomic
并使用acquire release memory ordering访问它。在大多数现代处理器上,插入的指令是内存围栏,它保证写入程序在开始写入之前等待所有加载完成,而读卡器在开始读取之前等待所有存储完成

此外,POSIX中还有锁定原语,但是
标题较新,可能是您想要的

标准怎么说 从[atomics.lockfree]中,强调添加了:

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

对于可锁定原子,标准在[thread.rec.lockable.general]中指出,强调增加了:

执行代理是可以与其他执行代理并行执行工作的实体,如线程。[…]实现或用户可以引入其他类型的代理,例如进程[…]

您有时会看到这样一种说法,即标准假定没有提到使用进程间共享内存的
原语,而只使用线程。这是不正确的


但是,通过共享内存将指针传递到另一个进程将不起作用,因为共享内存可能映射到地址空间的不同部分,当然,指向不在共享内存中的任何对象的指针是正确的。共享内存中对象的索引和偏移将被删除。(或者,如果您确实需要指针,Boost提供IPC安全包装。)

感谢您的快速响应。这些链接很有用。现在读。我好像有什么记忆障碍?由于需要以某种方式使缓存失效,缓存消费者必须强制缓存未命中或类似情况,因此将从共享内存中提取长度和数据。这就是我试图达到的“更深、更低级的理解”。谢谢没错,我认为std::atomic对于在线程之间共享数据非常有用。但这一次,我想在进程之间共享。添加了标准中关于使用进程间共享内存的
的内容。感谢引用该标准。我想我可以使用原子作为成员长度。但是会员数据呢?谢谢@Hei请不要评论说“谢谢”,投票和/或接受答案。@YSC我会在得到满意答案后立即回复。谢谢