代码之家  ›  专栏  ›  技术社区  ›  xyzzyrz

如何在POSIX中持久地重命名文件?

  •  18
  • xyzzyrz  · 技术社区  · 14 年前

    在POSIX文件系统中持久重命名文件的正确方法是什么?特别是想知道 目录

    :关于StackOverflow还有其他关于持久重命名的问题,但是它们没有解决fsync同步目录的问题(这对我来说很重要-我甚至没有修改文件数据)。

    我目前有(Python):

    dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY)
    rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename)
    fsync(dstdirfd)
    

    :

    • 这是否也隐式地fsync源目录?或者,我可能会在一次电源关闭后,文件显示在两个目录中(意味着我必须检查硬链接计数并手动执行恢复),也就是说,不可能保证持久的原子移动操作?
    • 目标目录,是否也会隐式地fsync目标目录?

    提前谢谢。

    4 回复  |  直到 13 年前
        1
  •  14
  •   Gray droiddeveloper    5 年前

    rename function must be atomic .

    但这并不能解决确保rename()操作持久的问题。 POSIX answers this question :

    因此,如果您fsync()一个目录,等待的重命名操作必须在返回时传输到磁盘。任何一个目录的fsync()都应该足够了,因为rename()操作的原子性要求两个目录的更改原子同步。

    fsync()函数用于强制从缓冲区缓存中物理写入数据,并确保在系统崩溃或其他故障后,fsync()调用之前的所有数据都记录在磁盘上。由于这里没有定义“缓冲缓存”、“系统崩溃”、“物理写入”和“非易失性存储”的概念,因此措辞必须更加抽象。

    (更新了附加信息:Linux特定与可移植行为)

        2
  •  16
  •   Robert Siemer    9 年前

    不幸的是,戴维的回答是错误的。

    真正的问题应该是:

    如何在通过posixapi支持持久重命名的系统上进行持久重命名?

    您需要对这两个源代码执行fsync()

    fsync(destdirfd)是否也隐式地fsync源目录?

    • POSIX概述:没有保证,但是您应该同时使用fsync()两个目录,这可能不是原子持久的
    • ext3/4:最少需要多少fsync()取决于装载选项。例如,如果安装了dirsync,你不需要这两个fsync()中的任何一个,最多你需要两个fsync(),但我几乎可以肯定一个就足够了(那么原子持久)。

    如果我fsync源目录而不是目标目录,这是否也会隐式fsync目标目录?

    • ext3/4:我真的相信两者最终都在同一个事务中,所以您fsync()中的哪一个并不重要
    • 旧内核ext3:(如果它们不在同一个事务中)一些不太理想的实现在fsync()上进行了太多的同步,我敢打赌它确实提交了之前的每个事务。是的,一个正常的实现会首先将它链接到目标,然后从源中删除它。因此fsync(srcdirfd)也会触发目标的fsync()。
    • ext4/latest ext3:如果它们不在同一事务中,您可能可以独立地完全同步它们(两个都可以)

    是否有任何有用的相关测试/调试/学习工具(故障注入器、自省工具、模拟文件系统等)?

        3
  •  -1
  •   Tom Pinckney    13 年前

    首先,我要阅读您正在使用的平台上的rename(2)手册页。

        4
  •  -4
  •   SpliFF    13 年前

    在我看来,你好像是在做文件系统的工作。如果移动文件,内核和文件系统负责原子操作和故障恢复,而不是代码。

    无论如何,本文似乎解决了您关于fsync的问题: http://blogs.gnome.org/alexl/2009/03/16/ext4-vs-fsync-my-take/