如何使用mmap创建检查点文件,该文件仅手动同步到磁盘

问题描述 投票:6回答:5

我需要最快的方法来定期将文件与内存同步。

我想我想拥有一个mmap文件,该文件仅手动同步到磁盘。我不确定如何防止任何自动同步的发生。

除非我手动指定,否则无法修改文件。关键是要有一个检查点文件,该文件将状态的快照保存在内存中。我想尽可能避免复制,因为这将需要相当频繁地调用,并且速度很重要。

c sync mmap
5个回答
2
投票

mmap不能用于此目的。无法阻止数据写入磁盘。实际上,使用mlock()使内存不可交换might具有防止将其写入磁盘的副作用,除非您要求将其写入磁盘,但这并不能保证。当然,如果另一个进程打开了文件,它将看到缓存在内存中的副本(具有您的最新更改),而不是物理磁盘上的副本。在许多方面,您应该采取的措施取决于您是要与其他进程进行同步还是出于崩溃或电源故障的安全性考虑。

如果数据量很小,您可以尝试其他多种方法来原子同步到磁盘。一种方法是将整个数据集存储在文件名中,并使用该名称创建一个空文件,然后删除旧文件。如果启动时存在2个文件(由于极不可能的崩溃时间),请删除较旧的文件,然后从较新的文件中恢复。如果您的数据大小小于文件系统块,页面大小或磁盘块,则write() may也是原子的,但是我不知道有任何保证立即生效。您必须进行一些研究。

另一种非常标准的方法,只要您的数据不是很大,就不能在磁盘上容纳2个副本:只需创建一个具有临时名称的第二个副本,然后将其复制到旧副本的顶部即可。 rename()始终是原子的。除非您有理由不这样做,否则这可能是最好的方法。


4
投票

您在文件的rename()映射内写入存储器的所有内容均被视为当时已写入文件,就像您曾经使用过MAP_SHARED一样。从这个意义上讲,write()完全类似于msync()-它只是确保您对文件的[[已经进行所做的更改实际上被推送到永久存储。您无法更改-这是fsync()的定义工作方式。

通常,执行此操作的安全方法是将数据的完整一致副本写入临时文件,同步该临时文件,然后在先前的检查点文件上原子重命名。这是确保检查点之间的崩溃不会导致文件不一致的唯一方法。任何复制较少的解决方案都将需要更复杂的事务日志样式的文件格式,并且对其他应用程序更具侵入性(要求在更改内存中状态的每个位置调用特定的挂钩) 。

2
投票
您可以mmap()作为写时复制的文件,这样您在内存中所做的任何更新都不会写回到文件中,然后当您要同步时,您可以:]

A)创建一个新的内存映射,该映射在写入时不复制,仅复制您修改后的页面。

B)通过直接I / O(块大小与读写大小对齐)打开文件(常规文件打开),并仅写入修改的页面。直接I / O既好又快速,因为您正在写整个页面(内存页面大小是磁盘块大小的倍数),并且没有缓冲。如果您的mmap()很大并且没有空间mmap()另一个巨大的文件,此方法的好处是不使用地址空间。

同步后,您写的副本mmap()与磁盘文件相同,但是内核仍然将您需要同步的页面标记为未共享(与磁盘共享)。因此,您可以关闭并重新创建mmap()(写时仍为复制状态),这样,如果有内存压力,内核可以在必要时丢弃您的页面(而不是分页以交换空间)。

当然,您必须跟踪自己修改过的页面,因为我无法想到您将如何访问操作系统保留该信息的位置。 (这不是方便的mmap()吗?)

-编辑-

实际上,有关如何查看哪些页面变脏的信息,请参阅syscall()


2
投票
正如其他受访者所建议的那样,我认为没有一种可复制的方式来做您想要的事,而无需复制。如果您希望在可以控制操作系统等的特殊环境中执行此操作,则可以在Linux下使用btrfs文件系统来执行此操作。

0
投票
我高度怀疑任何操作系统都可能不会利用它,但是操作系统可能会注意到以下方面的优化:
© www.soinside.com 2019 - 2024. All rights reserved.