当使用close()
或fclose()
(例如)closures文件时,Linux是否保证文件被写回(永久)光盘?
我的意思是,如果close()
返回0,然后立即电源失败,以前写入的数据保证坚持,即是持久的?
fsync()
系统调用确实提供了这个保证。 closures一个文件也足够了吗?
目前我找不到任何使这种或那种索赔的东西。
问题2:
如果close()
隐式做了一个fsync()
,有没有办法告诉它不?
从“ man 2 close
”:
成功关闭并不能保证数据已成功保存到磁盘,因为内核推迟写入。
手册页说,如果你想确保你的数据在磁盘上,你必须自己使用fsync()。
不,关闭不会执行fsync(2),并且如果这样做会击毁许多机器。 许多中间文件由其创建者打开和关闭,然后由用户打开和关闭,然后删除,如果close(2)执行自动fsync(2) ,这个非常常见的序列将需要接触磁盘。 相反,磁盘通常不会被触及,磁盘永远不会知道文件在那里。
注意fsync不能保证文件在磁盘上也是很重要的。 它只是保证操作系统已经要求文件系统刷新对磁盘的更改。 文件系统不必写任何东西到磁盘
从男人3 fsync
如果
_POSIX_SYNCHRONIZED_IO
没有被定义,则措辞在很大程度上依赖于一致性文档来告诉用户可以从系统中得到什么。 明确地打算允许空实现。
幸运的是,Linux的所有通用文件系统实际上都是将更改写入磁盘; 不幸的是,仍然不能保证文件在磁盘上。 许多硬盘驱动器随着写入缓冲打开(因此有自己的缓冲区,fsync不刷新)。 而一些驱动器/ RAID控制器甚至会骗你冲洗缓冲区。
不.fclose()并不意味着fsync()。 许多Linux文件系统会延迟写入和批量处理,从而提高整体性能,可能会减少磁盘驱动器的磨损,并延长笔记本电脑的电池寿命。 如果操作系统在文件关闭时不得不写入磁盘,则很多好处将会丢失。
保罗·汤姆林(Paul Tomblin)在他的回答中提到了一个争议,并且解释了我所看到的那个不适合发表评论。 以下是我所听到的:
最近的争议在于ext4的排序(ext4是流行的ext3 Linux文件系统的提议继承者)。 习惯上,在Linux和Unix系统中,通过读取旧文件来更改重要的文件,用不同的名称写出新文件,并将新文件重新命名为旧文件。 这个想法是确保即使系统在某个时候失败了,新的或旧的都将在那里。 不幸的是,ext4似乎很乐意阅读旧版本,将新版本重新命名为旧版本,然后编写新版本,如果系统在步骤2和步骤3之间停机,那么这可能是一个真正的问题。
处理这个问题的标准方法当然是fsync(),但是会影响性能。 真正的解决方案是修改ext4以保持ext3的排序,在那里它不会重命名一个文件,直到写完文件。 显然这不是标准所涵盖的,所以这是一个实现问题的质量,ext4的QoI在这里真的很糟糕,没有办法可靠地编写新版本的配置文件,而不需要经常调用fsync(),所有的问题导致或者冒着失去两个版本的风险。
不,不能保证。 操作系统有它自己的缓存。 所有关闭的真正的保证是程序缓冲区刷新到操作系统,但操作系统可能仍然坚持它不成文。 我相信Linux内核领域存在一些争议,因为即使fsync也不能保证将其刷新到磁盘上,至少在ext3中是如此。
开放的manpage说:
为了保证同步I / O,除了O_DIRECT之外,还必须使用O_SYNC 。
然后
一般来说这(O_DIRECT)会降低性能。
我们可以使用fcntl和F_SETFL来切换这个标志,这样可以最大限度地减少I / O对每个读写操作的缓存效果 。
您可能也对firebird sql数据库中关于fcntl(O_SYNC)不能在linux上工作的bug报告感兴趣。
另外,你问的问题意味着一个潜在的问题。 写入磁盘是什么意思? 为什么这有关系? 你是否担心电源熄灭,驱动器中的文件丢失? 为什么不在系统或SAN上使用UPS?
在这种情况下,您需要一个日志文件系统 – 而不仅仅是一个元数据日志文件系统,而是一个完整的日志,即使是所有的数据。
即使在这种情况下,你也必须明白,除了O / S的参与外, 大多数硬盘都在骗你做fsync。 – fsync只是将数据发送到驱动器,由个人操作系统知道如何等待驱动器刷新自己的缓存。
–jeffk ++
我不认为Linux可以保证这一点,因为驱动器本身也可以缓存数据。
如果计算机/操作系统具有容错文件系统,那么我们就不必关心这个问题了,如果我们把这个限制放在文件上的话,那么这个文件系统肯定会写入一个重启周期中的东西。 如果有一些非易失性的RAM或等价物,它不一定是磁盘。 我记忆犹新的一些大型主机确实有这样的机制,据说确实做出了这样的保证。