【问题标题】:Does Linux guarantee the contents of a file is flushed to disc after close()?Linux 是否保证文件的内容在 close() 后刷新到磁盘?
【发布时间】:2010-10-16 20:50:23
【问题描述】:

当使用close()fclose()(例如)关闭文件时,Linux 是否保证将文件写回(永久)磁盘?

我的意思是,如果close() 返回 0,然后立即断电,之前写入的数据是否可以保证持续存在,即持久?

fsync() 系统调用确实提供了这种保证。关闭文件也够了吗?

我目前找不到任何可以以某种方式提出索赔的东西。


问题 2:

如果close() 确实隐式执行fsync(),有没有办法告诉它不要这样做?

【问题讨论】:

  • 一个相关的问题是close()之后是否可以重新打开文件到fsync()。我找不到任何权威的答案。这是open question

标签: linux file-io filesystems


【解决方案1】:

来自“man 2 close”:

成功关闭并不能保证数据已被 成功保存到磁盘,因为 内核延迟写入。

手册页说如果你想确保你的数据在磁盘上,你必须自己使用 fsync()。

【讨论】:

    【解决方案2】:

    不,关闭 不会执行 fsync(2) 并且如果这样做会导致许多机器死亡。许多中间文件由它们的创建者打开和关闭,然后由它们的使用者打开和关闭,然后删除,如果 close(2) 执行自动 ,这个非常常见的顺序将需要触摸磁盘fsync(2)。相反,磁盘通常不会被触及,并且磁盘永远不会知道文件在那里。

    【讨论】:

    • 你确定吗?你有这方面的参考吗?
    • 是的;要关闭(2)的手册页中提到不执行同步。对于更大的文件系统缓存问题,请参阅任何涵盖操作系统中现代磁盘缓存的优秀文本,例如 Hennessy 和 Patterson 的“定量”操作系统教科书。
    • 即使 'fsync()' 也不是万无一失的 .. 磁盘控制可能至少在一小部分时间内缓存数据...
    【解决方案3】:

    同样重要的是要注意 fsync 不保证文件在磁盘上;它只是保证操作系统已要求文件系统刷新对磁盘的更改。文件系统不必向磁盘写入任何内容

    来自man 3 fsync

    如果_POSIX_SYNCHRONIZED_IO 未定义,则措辞严重依赖 在一致性文档上告诉用户可以预期什么 从系统。明确的意图是空实现 是允许的。

    幸运的是,Linux 的所有常见文件系统实际上都会将更改写入磁盘;不幸的是,仍然不能保证文件在磁盘上。许多硬盘驱动器都打开了写缓冲(因此有自己的 fsync 不会刷新的缓冲区)。还有一些 drives/raid controllers even lie to you 已经刷新了他们的缓冲区。

    【讨论】:

      【解决方案4】:

      没有。 fclose() 并不意味着 fsync()。许多 Linux 文件系统延迟写入并将它们批处理,这提高了整体性能,可能减少了磁盘驱动器的磨损,并提高了笔记本电脑的电池寿命。如果操作系统必须在文件关闭时写入磁盘,那么这些好处中的许多都将失去。

      Paul Tomblin 在他的回答中提到了一个争议,并且解释我所看到的不适合发表评论。以下是我听到的:

      最近的争议是关于 ext4 的排序(ext4 是流行的 ext3 Linux 文件系统的拟议继任者)。在 Linux 和 Unix 系统中,习惯上通过读取旧文件、用不同名称写出新文件并将新文件重命名为旧文件来更改重要文件。这个想法是确保即使系统在某个时候出现故障,新的或旧的都会在那里。不幸的是,ext4 似乎很乐意读取旧的,将新的重命名为旧的,然后写入新的,如果系统在步骤 2 和 3 之间出现故障,这可能是一个真正的问题。

      处理这个问题的标准方法当然是 fsync(),但这会破坏性能。真正的解决方案是修改 ext4 以保持 ext3 的顺序,在它完成写出文件之前不会重命名文件。显然这不在标准中,所以这是一个实现的质量问题,而 ext4 的 QoI 在这里真的很糟糕,如果不不断调用 fsync() 就无法可靠地编写新版本的配置文件,所有问题这会导致或有丢失两个版本的风险。

      【讨论】:

      • 也许我就是这么想的。我应该问问那些我听到抱怨的人,他们到底在抱怨什么。
      • 这是最近在 Slashdot 上的大文件系统咆哮,无论如何。我在那里建议 C++ 系统通过空指针取消引用向你的老板发送一封讨厌的辞职信和你的色情收藏 (/.meme) 给你妈妈,这同样符合标准。
      • Ext4 的较新版本有一个选项可以打开类似 Ext3 的 data=ordered 选项:thread.gmane.org/gmane.comp.file-systems.ext4/12179
      【解决方案5】:

      不,不能保证。操作系统有自己的缓存。所有关闭的真正保证是程序缓冲区被刷新到操作系统,但操作系统可能仍然保留它未写入。我相信在 Linux 内核世界中存在一些争议,因为即使 fsync 也不能保证它被刷新到磁盘,至少在 ext3 中是这样。

      【讨论】:

      • 请提供一个引用,如果 fsync() 没有做它应该做的事情,那将是一个可怕的错误。
      • 即它会完全破坏数据库的持久性。
      • 我看到的争议是另外一回事,不适合评论。我正在为它写一个答案。
      【解决方案6】:

      open 的手册页说:

      为了保证同步 I/O,除了 O_DIRECT 之外,还必须使用 O_SYNC

      还有那个

      一般来说,这 (O_DIRECT) 会降低性能。

      可以使用 fcntlF_SETFL 来切换此标志,以便 最大程度地减少每次读取和写入时 I/O 的缓存影响之后。

      【讨论】:

        【解决方案7】:

        您可能还对 firebird sql 数据库中的这个 bug report 感兴趣,因为 fcntl( O_SYNC ) 在 linux 上不起作用。

        此外,您提出的问题暗示了一个潜在问题。写入磁盘是什么意思?为什么这有关系?您是否担心断电并且驱动器中缺少文件?为什么不在系统或 SAN 上使用 UPS?

        在这种情况下,您需要一个日志文件系统 - 而不仅仅是元数据日志文件系统,甚至是所有数据的完整日志。

        即使在这种情况下,您也必须了解,除了操作系统的参与之外,most hard disks lie to you about doing an fsync. - fsync 只是将数据发送到驱动器,由各个操作系统知道如何等待驱动器刷新它自己的缓存。

        --jeffk++

        【讨论】:

          【解决方案8】:

          我认为 Linux 不能保证这一点,因为驱动器本身也可以缓存数据。

          【讨论】:

          • 但是如果驱动器被告知不要这样做,或者(更常见的)是电池支持的 RAID 控制器,原则上应该能够提供这种保证。
          • 原则上可能是这样,但实际上这肯定不是常态。
          • 那是驱动的问题,那么,如果它可以报告它成功地写了一些东西并撒了谎。一旦设备驱动程序确信它已写入磁盘,Linux 就完成了它所能做的一切。
          • 拥有硬件写入缓存的重点是在写入操作完成之前不会阻塞操作系统。驱动器别无选择,只能“撒谎”。请不要误会我的意思,我并没有把责任归咎于 Linux,我只是说 Linux 不能保证这一点,即使它做出了很好的努力。
          • 驱动程序真的对操作系统撒谎吗?我对这方面一无所知,但我一直认为它会回答“我知道了”,然后当它真的回复时说“我写了它”......我还认为操作系统有一种方法可以要求它立即写.这些假设不正确吗?
          【解决方案9】:

          如果计算机/操作系统有一个容错文件系统,可以保证写入至少在我们施加此约束的文件上能在电源循环后幸存下来的内容,我们就不必关心这一点。如果有一些非易失性 RAM 或等效物,则不必是磁盘。我依稀记得的一些过去时代的大型机确实有这样的机制,并且据说确实做出了这样的保证。

          【讨论】:

          • 大多数现代服务器级 RAID 控制器都具有此功能(电池支持缓存)。但是,到控制器的总线速度是有限的,因此操作系统通常只会在应用程序特别请求时才等待“写入”数据。正如这个问题的答案所示。
          猜你喜欢
          • 2012-11-25
          • 1970-01-01
          • 2015-07-03
          • 2012-06-19
          • 2015-03-05
          • 2012-02-18
          • 1970-01-01
          • 1970-01-01
          • 2017-03-02
          相关资源
          最近更新 更多