【问题标题】:Shared Memory using CreateFileMapping + MapViewOfFile使用 CreateFileMapping + MapViewOfFile 共享内存
【发布时间】:2015-08-08 00:51:12
【问题描述】:

我有两个线程:reader 和 writer。两者都通过 CreateFileMapping + MapViewOfFile 分配的内存进行通信。两者的工作速度都相对较快。两者都异步工作。

问题:阅读器有时会得到零值。而且我绝对确定这不是作者提供的。 writer 提供的值永远不会为零。

我相信当作者和读者试图同时访问内存时会发生这种情况。我希望“CreateFileMapping + MapViewOfFile”机制能够自动解决这类问题。我弄错了吗?我是否需要添加事件来同步对共享内存的访问?

【问题讨论】:

  • 写入内存需要时间。当您写入共享内存时,您处于不确定状态。写入操作完成后,更改将反映到所有映射视图。无论如何,您都必须同步读取和写入,以建立一致的结果。
  • 1) 为什么我得到零值?不是以前的值? 2)是否可以检测到“读取”功能无法获取数据?某种 GetLastError?
  • 不清楚为什么零是一个问题:你不知道你读什么、写什么、怎么写。可能是零写入是写入操作的一部分,而读者在写入处于其任务中间时接受了这一点。
  • 零是一个问题,因为我绝对确定作者正在赋予不同的价值。它永远不会是零。
  • 您需要post an MCVE。问题中没有足够的信息让我们猜测您可能做错了什么,尽管通常您需要某种类型的同步。

标签: winapi


【解决方案1】:

文件的视图在应用程序之间同步如果后备文件是本地的。

MSDN:

除了一个重要的例外,从由同一文件支持的任何文件映射对象派生的文件视图在特定时间是连贯的或相同的。一个进程内的视图和不同进程映射的视图的一致性得到保证。

异常与远程文件有关。尽管 CreateFileMapping 可以处理远程文件,但它并不能保持它们的一致性。例如,如果两台计算机都将文件映射为可写,并且都更改同一页面,则每台计算机只能看到自己对该页面的写入。当数据在磁盘上更新时,它不会被合并。

这当然只涉及已完成的写入和读取。

  • 备份文件是本地的(包括:由交换文件备份)
  • 在写入成功返回之前不要尝试读取

所以如果 - 正如你所说 - 写入器和读取器异步运行,您可能需要自己的同步机制。

这可能是使用事件/mutice,也可能只是文件中的数据。


例子:

文件的内容是记录的环形缓冲区。在映射内存区域的开头(或结尾),有一个写指针。

添加记录意味着

  1. 将新记录写入内存
  2. 更新写指针

阅读记录意味着:

  1. 读取写入指针以检测是否有新记录
  2. 如果有新记录,请阅读它们

顺序很重要。对于环形缓冲区,通常还需要引入一个读指针来防止覆盖未读记录。

确保测试写/读操作的返回值并相应地处理错误。

请记住,内存映射文件访问可能会引发您的应用程序应处理的访问冲突异常。

【讨论】:

  • 基本上你的意思是 - 读取值,如果它是零然后再试一次?正确的?还是有办法验证返回值?
  • @walruz:“你 [...] 需要你自己的同步机制”。破解正确同步的方法不会有好的结果。你怎么知道零不是有效值?您在哪里读到,不确定的数据将始终设置为零?咬紧牙关,实现同步。
  • @walruz:读取值,如果为零,则再试一次? 否 - 请再次阅读示例。
  • @peterchen:“确保你测试了写/读操作的返回值”你是什么意思?我该怎么做?
  • @walruz:WinAPI 可以只负责同步视图,它不能知道你打算写什么,你的数据意味着什么等。在一般情况下,WinAPI 无法同步您的读取和写入。
猜你喜欢
  • 2012-01-26
  • 1970-01-01
  • 2011-02-07
  • 2012-06-19
  • 2017-11-11
  • 2010-12-25
  • 2019-03-07
  • 1970-01-01
  • 2015-06-15
相关资源
最近更新 更多