Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.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++ 共享内存-需要同步_C++_Windows_Concurrency_Shared Memory - Fatal编程技术网

C++ 共享内存-需要同步

C++ 共享内存-需要同步,c++,windows,concurrency,shared-memory,C++,Windows,Concurrency,Shared Memory,我看过一个项目,其中进程之间的通信是使用共享内存进行的(例如,在Windows下使用::CreateFileMapping),每当其中一个进程想要通知共享内存中有一些数据可用时,使用命名事件的同步机制通知相关方共享内存的内容已更改 我担心的是,对于读取新信息的进程来说,不存在适当的内存围栏,以便知道它必须使其数据副本无效,并在生产者进程“发布”数据后从主内存中读取数据 您知道如何在Windows上使用共享内存实现这一点吗 编辑 只是想补充一点,在创建文件映射之后,进程只使用MapViewOfFi

我看过一个项目,其中进程之间的通信是使用共享内存进行的(例如,在Windows下使用
::CreateFileMapping
),每当其中一个进程想要通知共享内存中有一些数据可用时,使用命名事件的同步机制通知相关方共享内存的内容已更改

我担心的是,对于读取新信息的进程来说,不存在适当的内存围栏,以便知道它必须使其数据副本无效,并在生产者进程“发布”数据后从主内存中读取数据

您知道如何在Windows上使用共享内存实现这一点吗

编辑
只是想补充一点,在创建文件映射之后,进程只使用MapViewOfFile()API一次,对共享数据的每次新修改都使用初始调用MapViewOfFile()获得的指针来读取通过共享内存发送的新数据。正确的同步是否要求每次在共享内存中更改数据时,每次读取数据的进程都必须创建MapViewOfFile()。

让我们将进程A称为数据生产者,将进程B称为数据消费者。到目前为止,您已经有了一种机制,流程a可以通知流程B新数据已经生成。我建议您创建一个反向通知(从B到a),通知流程a数据已被使用。如果出于性能原因,您不希望进程A等待数据被消耗,您可以在共享内存中设置A。

在windows上寻找共享内存的是InterlockedExchange功能。看。引用了真正重要的部分:

此函数生成一个完整的内存屏障(或围栏),以确保 内存操作按顺序完成

这将在整个过程中发挥作用。我以前使用过它,发现它在共享内存之上实现类似互斥的构造是100%可靠的

这样做的方法是将其与“set”值交换。如果你得到“清除”回来,你有它(它是明确的),但如果你得到“设置”回来,那么别人有它。你循环,在循环之间睡觉,等等,直到你“得到”它。基本上:

#define LOCK_SET 1
#define LOCK_CLEAR 0

int* lock_location = LOCK_LOCATION; // ensure this is in shared memory
if (InterlockedExchange(lock_location, LOCK_SET) == LOCK_CLEAR)
{
    return true; // got the lock
}
else
{
    return false; // didn't get the lock
}

如上所述,循环直到“获取”它。

如果使用Windows命名事件来发送更改信号,那么一切都应该正常

进程A更改数据并调用
SetEvent

进程B使用
WaitForSingleObject
或类似工具等待事件,并查看它是否已设置

然后进程B读取数据
WaitForSingleObject
包含所有必要的同步,以确保进程B在调用
SetEvent
之前读取进程A所做的更改

当然,如果您在调用
SetEvent
之后对数据进行任何更改,则这些更改可能会在进程B读取数据时显示,也可能不会显示

如果不想使用事件,可以使用通过
CreateMutex
创建的互斥锁,或者可以使用
Interlocked…
函数编写无锁代码,如
InterlockedExchange
InterlockedIncrement


无论您如何执行同步,都不需要多次调用
MapViewOfFile

要成为有效的同步机制,命名事件应该有适当的内存隔离。你有证据表明这种情况可能不会发生吗?@Alexey:的确,通常是这样,但它是否有标准/规范/等的保证?在windows上,可以使用CreateEvent api进行同步。我不知道设置和等待该事件是否会产生获取/发布必需的mem fences thoughYes,但如何确保消费者看到数据发布?@Ghita默认情况下,x86体系结构是缓存一致的。由一个处理器进行的写操作总是被同一个处理器或同一系统的其他处理器的后续读取看到。您所要做的就是确保编译器在数据写入共享内存后调用通知函数。我认为您应该将内存标记为“volatile”(在C中),以保证这一点。我认为,即使在x86上,对于performance@GhitaIIRC,x86体系结构使用协议实现缓存一致性。在写入内存“区域”(即缓存线)之前,处理器需要拥有它。处理器只允许读取缓存线,如果它是所有者或缓存线没有所有者。因此,我这里有一个互斥实现,可以使用命名的win critical部分,但如何在生产者和消费者进程上使用它?您的问题是如何在共享内存中创建同步机制。这将允许您完全做到这一点。从这里,您可以在共享内存中设计自己的计数器集或受此保护的其他变量。如果您自己不知道如何实现这种同步,您需要阅读一些关于同步的基础知识。但如果您所需要的只是生产者-消费者,我会研究命名管道或套接字或其他进程间通信。共享内存并不总是解决简单问题的最佳选择。我只需要知道平台为我需要的东西提供了什么保证。我从MSDN文章中引用的是,保证指向同一共享内存的两个进程,如果通过此函数使用,它将是原子的。我自己也做过(这不是“理论上”的代码,而是在生产中)。我不知道你还想要什么。只是一个关于tnx支持的问题的解决方案