在 Linux 上,众所周知,之后:
creat(path,..)
、open(new_path,O_CREAT..)
),或unlink(path)
),或rename(src_path,dst_path)
)还应该确保对目录的更改(在某种意义上是将人类可读名称映射到索引节点的另一个文件)也已以持久的方式持久保存到光盘上(否则,在断电的情况下,或者拍摄卷的快照,该目录可能看起来没有新内容)。换句话说,这些函数在目录更改持久之前返回(这有点道理,因为 FS 更像是 DAG 而不是树,所以甚至不清楚哪些目录需要更新)。
可以使用
open(path_to_parent_dir)
获取目录的文件描述符,然后 fsync(..)
(以及 close(..)
)。
在Windows上,我看到在
MoveFileExA(src_path,dst_path,flags)
的情况下,我可以提供MOVEFILE_WRITE_THROUGH
标志,一方面实现了重命名的持久性,另一方面证明了该问题通常适用也适用于 Windows。
因此,我想知道:其他操作怎么样,例如:
CreateFile(path,...)
与OS_FILE_CREATE
),或DeleteFile(path)
)。这些函数是否确保对包含
path
的目录的更改在返回之前是持久的,或者我应该调用一些额外的函数来实现持久性?
如果是这样,我该怎么办?像这样的吗?
const auto dir_handle = CreateFile(path_to_parent_dir,...,FILE_FLAG_BACKUP_SEMANTICS,...);
FlushFileBuffers(dir_handle);
CloseHandle(dir_handle);
一般来说,不会,对于大多数应用程序来说,Windows 文件系统的内部机制(包括缓存策略)可确保对目录的更改在无需刷新操作的情况下持久存在。这些机制旨在从错误中恢复。
特定情况,是:在您的应用程序需要严格保证更改(例如文件创建、删除或重命名)立即保留的情况下,您可能会考虑刷新目录更改。这可能与处理必须在磁盘上立即保持一致的关键数据的应用程序相关,例如金融交易日志、配置文件或文件系统的精确状态在更改后立即至关重要的其他情况。 如果您确定刷新目录更改对于您的应用程序是必要的,则该方法涉及使用
CreateFile
函数通过 FILE_FLAG_BACKUP_SEMANTICS
打开目录,然后调用 FlushFileBuffers
以确保将更改写入磁盘,并且最后,用CloseHandle
关闭手柄。此方法强制文件系统将目录列表中的任何更改提交到磁盘,以确保持久性。
仔细阅读文档,您可能不会遇到类似“Windows 上总是/从不需要刷新目录”这样的明确声明。这种模糊性通常源于系统的设计,其中某些行为是隐含的而不是明确声明的。