【问题标题】:how to (f)sync a directory under linux in c如何(f)在c中同步linux下的目录
【发布时间】:2018-12-08 14:06:08
【问题描述】:

我有一些 linux 下的 c 应用程序。我正在用rename(...) 重命名一些文件 如何确保将重命名持久写入底层磁盘?

使用文件我可以执行以下操作:

FILE * f = fopen("foo","w");
...
fflush(f);
fsync(fileno(f));
fclose(f);

如何在 c 中 rename() 之后的目录 fsync(或类似)?

【问题讨论】:

    标签: c filesystems fsync


    【解决方案1】:

    根据manual,在函数返回时,rename已经有效完成(返回0)或发生错误(返回-1)并设置errno检查错误。

    如果您希望系统在rename 之后仅在此文件上应用潜在的未决修改,您可以这样做:

    int fd = open(new_name, O_RDONLY);
    syncfs(fd);
    

    【讨论】:

      【解决方案2】:

      rename() 是原子的(在 linux 上),所以我认为您无需担心

      原子性通常在涉及文件名处理的操作中得到保证;例如,对于重命名,“规范要求函数的操作是原子的”——也就是说,当将文件从旧名称重命名为新名称时,在任何情况下都不应同时看到这两个文件。

      rename() 操作过程中的断电不应使文件系统处于“奇怪”状态,文件名由于其元数据已损坏而无法访问。 (即,要么操作丢失,要么操作已提交。)

      Source

      所以,我认为你应该只担心错误值。


      如果你真的想要安全,fsync() 也会刷新元数据(在 linux 上),所以你可以fsync 确保磁盘上存在你想要的目录和文件。

      【讨论】:

      • 它在 POSIX 系统上是原子的。 C 标准对此只字未提。
      • 如何获取目录的“文件句柄”?
      • @powerpete 我认为您可以像打开任何其他文件一样打开目录(仅读取模式)
      • opendir(..)?打开(...)? fopen(...)?
      • @powerpete 你经常用opendir() 打开文件吗? open()fopen() 可以完成这项工作,我认为 opendir() 不会被 fsync() 接受,因为它有点特别。
      【解决方案3】:

      这就是你可以做你想做的事:

      #include <fcntl.h>
      int fd = open('/path/to/dir', O_RDONLY);
      fsync(fd);
      

      当然不要忘记在不再需要时关闭 fd 文件描述符。

      与一些误解相反,rename() 的原子性并不能保证文件会被持久化到磁盘。原子性保证只确保文件系统缓冲区中的元数据处于一致状态,但不能确保已持久化到磁盘。

      【讨论】:

        猜你喜欢
        • 2012-01-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-15
        • 2015-04-03
        • 2014-02-02
        • 1970-01-01
        相关资源
        最近更新 更多