共享内存 – 需要同步

我见过一个使用共享内存进行进程之间通信的项目(例如,在Windows下使用::CreateFileMapping ),并且每次有一个进程想要通知在共享内存中有一些数据可用时,使用通知事件的同步机制感兴趣的一方,共享内存的内容发生了变化。

我担心这样的事实,即在读取新信息的过程中不存在适当的内存隔离,以知道它必须使其数据的副本无效,并且一旦由生产者过程“发布”就从主存储器读取它。

你知道如何在Windows上使用共享内存来完成吗?

编辑只是想添加,创build文件映射后,进程使用MapViewOfFile()API只有一次,每个新的修改共享数据使用获得的初始调用MapViewOfFile()读取通过共享内存发送的新数据。 正确的同步是否要求每次共享内存中的数据更改时,读取数据的进程每次都必须创buildMapViewOfFile()?

如果您使用Windows命名事件来更改信号,则一切都应该正常。

进程A更改​​数据并调用SetEvent

进程B使用WaitForSingleObject或类似的等待事件,并看到它被设置。

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

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

如果您不想使用事件,则可以使用CreateMutex创建的互斥锁,也可以使用InterlockedExchangeInterlockedIncrementInterlocked...函数编写无锁定代码。

然而,你做同步,你不需要多次调用MapViewOfFile

您在Windows上寻找共享内存的是InterlockedExchange函数。 请参阅这里的MSDN文章 。 引用真正重要的部分:

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

这将起到跨进程的作用。 之前我曾经使用它,并发现它在共享内存之上实现类似互斥体的构造是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 } 

如上所述,并循环,直到你“得到”它。

让我们调用过程A的数据生产者和过程B的数据消费者。 到目前为止,您有一个流程A的机制来通知流程B已经产生了新的数据。 我建议你创建一个反向通知(从B到A),告诉进程A数据已被使用。 如果出于性能原因,您不希望进程A等待数据被使用,则可以在共享内存中设置环形缓冲区 。