【问题标题】:MapViewOfFile doesn't cause reading from a fileMapViewOfFile 不会导致从文件中读取
【发布时间】:2017-09-22 15:35:33
【问题描述】:

我有一个代码在重新映射之前使用 MapViewOfFile 和 FlushViewOfFile 写入文件。

我还有第二个代码,它在同一进程的其他线程中使用 MapViewOfFile 从同一个文件(在磁盘上,而不是 HANDLE/映射对象)读取。

视图的标志是 PAGE_READONLY/FILE_READ 和 PAGE_READWRITE/FILE_WRITE。

在我的电脑上一切正常。 但是当相同的构建作为服务在其他 PC 上运行时,它有一个奇怪的错误: 当我用偏移量 == 0 重新映射阅读器(这意味着 UnmapViewOfFile + MapViewOfFile)(以读取一些文件头)时,它不会返回任何错误,但读取本身会返回一些旧值,这些值已经被其他线程更改。

当我打开 ProcessMonitor 时,它显示没有从 offset = 0 读取,只有写入。

所以,问题是新调用 CreateFileMapping/MapViewOfFile 成功返回,但映射了一些旧的缓存页面,并且没有从文件中读取新数据。

再一次,同样的构建在我的 PC 上运行良好。

任何人都可以提出一些建议吗?谢谢。

【问题讨论】:

  • 看起来问题出在 FlushViewOfFile 上。我已将阅读切换到简单的 ReadFile,它在本地电脑上运行良好,但是当我尝试从另一台电脑(使用简单的 ReadFile)读取此文件时也会出现同样的问题..

标签: winapi mmap


【解决方案1】:

来自documentation for MapViewOfFile

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

换句话说,您观察到的行为符合预期。

还有:

文件的映射视图不能保证与 ReadFile 或 WriteFile 函数正在访问的文件一致。

由于您需要网络上的一致性,因此您不能使用文件映射。您必须使用 ReadFile 来读取内容并使用 WriteFile 来修改它们。您还应该使用 LockFile 或其他一些方法来协调对文件的访问,以确保您正在读取的数据是一致的。

(您还应该注意,取消映射然后重新映射完全相同的视图是没有用的。这基本上是无操作的。)

【讨论】:

  • 感谢您的回答。看起来你是对的。但我会注意到,文件中的两个引用都不是我的情况。我的程序所做的是 - 写入视图,然后将其刷新(!!)到磁盘,并从不同的线程读取这个文件(使用其他视图)。所以,我不能做的是强制 CreateFileMapping/MapVIewOfFile 从磁盘读取,即使我“关闭” FileMapping 然后再次“创建”它。我想重新打开文件描述符可能会有所帮助..(是的,这远非良好的性能)
  • FlushViewOfFile 并没有真正改变任何东西。它没有引入任何额外的一致性保证。 (由于它也不保证数据已经被物理写入,我实际上不确定它对什么有用,如果有的话。)数据在服务器和客户端都被缓存,FlushViewOfFile 没有不会影响另一台计算机上的缓存。
  • 我在 FlushViewOfFile 之后也添加了 FlushFileBuffers
  • 这会强制系统将更改刷新到磁盘驱动器,从而降低系统断电时数据丢失的风险。我认为这在使数据对远程进程可见方面没有帮助。 (或者至少不能保证它会这样做。)
猜你喜欢
  • 2010-09-20
  • 1970-01-01
  • 1970-01-01
  • 2021-08-29
  • 2019-06-19
  • 1970-01-01
  • 2015-02-18
  • 2020-07-23
  • 1970-01-01
相关资源
最近更新 更多