我需要最快的方法来定期将文件与内存同步。
我想我想拥有一个mmap文件,该文件仅手动同步到磁盘。我不确定如何防止任何自动同步的发生。
除非我手动指定,否则无法修改文件。关键是要有一个检查点文件,该文件将状态的快照保存在内存中。我想尽可能避免复制,因为这将需要相当频繁地调用,并且速度很重要。
mmap
不能用于此目的。无法阻止数据写入磁盘。实际上,使用mlock()
使内存不可交换might具有防止将其写入磁盘的副作用,除非您要求将其写入磁盘,但这并不能保证。当然,如果另一个进程打开了文件,它将看到缓存在内存中的副本(具有您的最新更改),而不是物理磁盘上的副本。在许多方面,您应该采取的措施取决于您是要与其他进程进行同步还是出于崩溃或电源故障的安全性考虑。
如果数据量很小,您可以尝试其他多种方法来原子同步到磁盘。一种方法是将整个数据集存储在文件名中,并使用该名称创建一个空文件,然后删除旧文件。如果启动时存在2个文件(由于极不可能的崩溃时间),请删除较旧的文件,然后从较新的文件中恢复。如果您的数据大小小于文件系统块,页面大小或磁盘块,则write()
may也是原子的,但是我不知道有任何保证立即生效。您必须进行一些研究。
另一种非常标准的方法,只要您的数据不是很大,就不能在磁盘上容纳2个副本:只需创建一个具有临时名称的第二个副本,然后将其复制到旧副本的顶部即可。 rename()
始终是原子的。除非您有理由不这样做,否则这可能是最好的方法。
您在文件的rename()
映射内写入存储器的所有内容均被视为当时已写入文件,就像您曾经使用过MAP_SHARED
一样。从这个意义上讲,write()
完全类似于msync()
-它只是确保您对文件的[[已经进行所做的更改实际上被推送到永久存储。您无法更改-这是fsync()
的定义工作方式。
mmap()
作为写时复制的文件,这样您在内存中所做的任何更新都不会写回到文件中,然后当您要同步时,您可以:]A)创建一个新的内存映射,该映射在写入时不复制,仅复制您修改后的页面。
或
B)通过直接I / O(块大小与读写大小对齐)打开文件(常规文件打开),并仅写入修改的页面。直接I / O既好又快速,因为您正在写整个页面(内存页面大小是磁盘块大小的倍数),并且没有缓冲。如果您的mmap()
很大并且没有空间mmap()
另一个巨大的文件,此方法的好处是不使用地址空间。
同步后,您写的副本mmap()
与磁盘文件相同,但是内核仍然将您需要同步的页面标记为未共享(与磁盘共享)。因此,您可以关闭并重新创建mmap()
(写时仍为复制状态),这样,如果有内存压力,内核可以在必要时丢弃您的页面(而不是分页以交换空间)。
当然,您必须跟踪自己修改过的页面,因为我无法想到您将如何访问操作系统保留该信息的位置。 (这不是方便的mmap()
吗?)
-编辑-
实际上,有关如何查看哪些页面变脏的信息,请参阅syscall()
。