delphi 内存Map文件可选写入可能吗?

t40tm48m  于 2023-06-22  发布在  其他
关注(0)|答案(2)|浏览(143)

当使用内存Map文件时,它似乎是只读或只写的。我的意思是你不能:

  • 打开一个文件以进行写入,然后决定不保存它
  • 已打开以供阅读,然后决定保存它

我们的应用程序使用一个可写的内存Map文件来保存数据文件,但由于用户可能希望退出而不保存更改,因此我们必须使用一个临时文件,用户实际上可以编辑该文件。当用户选择保存更改时,原始文件将被临时文件覆盖,因此它具有最新的更改。这很麻烦,因为文件可能非常大(>1GB),复制它们需要很长时间。
我尝试了许多用于创建文件Map的标志组合,但似乎没有一个允许按需保存的灵活性。有人能证实这一点吗?我们的应用程序是用 Delphi 编写的,但是在我们的例子中,它使用标准的API来创建Map

FMapHandle := CreateFileMapping(FFileHandle, nil, PAGE_READWRITE, 0, 2 * 65536, nil);
FBasePointer := MapViewOfFile(FileMapHandle, FILE_MAP_WRITE, FileOffsetHigh,
FileOffsetLow, NumBytes);
baubqpgj

baubqpgj1#

我觉得你做不到我的意思是你 * 可能 * 可以 *,但这对我来说没有任何意义:-)
内存Map文件的全部意义在于它是指向实际文件的窗口。如果你不想在文件中反映任何变化,你可能不得不做一些事情,比如批量处理数据结构中的变化(例如,基址,大小和数据的数组),并在保存时应用它们。
在这种情况下,您实际上并不需要内存Map文件,只需读入并维护您想要更改的块(如果有多用户访问的机会,请首先锁定文件)。

  • 更新:*

你有没有想过这样的可能性,当做一个保存,删除原始文件,只是重命名临时文件的原始文件名?这可能比将1G的数据从临时数据复制到原始数据要快得多。这样,如果您不想保存它,只需删除临时文件并保留原始文件。
加载时,您仍然需要将原始数据复制到临时文件中,但不必将临时数据复制回来(无论是否保存)-这将使所需时间减半。

mgdq6dx1

mgdq6dx12#

有可能,但并非微不足道。
您必须了解内存Map的基础知识,以及内存Map文件的三种模式之间的区别。两者都留出一部分虚拟地址空间,并在内部表中创建一个Map条目。最初不分配物理RAM。因此,当你尝试访问内存时,CPU会出现故障,操作系统必须修复。它通过将文件内容复制到RAM并将RAMMap到您的进程的错误地址来实现。
现在,这三种模式之间的区别在于如何在Map页面上设置描述符。在所有情况下,您都可以在页面上获得读取访问权限。(第一种模式)。但是,如果您请求写访问权限并随后对其进行写入,则在第一次写入时,该页将被标记为可写和脏。然后可以根据操作系统的判断将其写回原始文件(第二模式)。最后,可以获得写时复制语义。开始时,您仍然只能对内存中的页面进行读访问。当你写它的时候,CPU仍然会出错,操作系统需要修复它。对于写时复制,通过将更改页的后备存储设置为页文件而不是原始Map文件来完成修复。
因此,在您的情况下,您希望使用写时复制模式。如果用户决定放弃修改,没有问题。您只需丢弃内存Map。在内存中修改过的所有页,并由页文件支持。
如果用户决定保存,您的任务就稍微困难一些。您现在需要弄清楚文件的哪些部分发生了更改。这些更改位于内存中,您需要将它们重新应用到源文件。你可以用Page Guards来实现。因此,当用户决定保存时,将所有修改的页面复制到单独的内存块,重新Map(未更改的)文件以进行写入,并应用更改。

相关问题