file.flush() 到底在做啥?

Posted

技术标签:

【中文标题】file.flush() 到底在做啥?【英文标题】:What exactly is file.flush() doing?file.flush() 到底在做什么? 【发布时间】:2011-10-30 22:08:10 【问题描述】:

我在 Python documentation for File Objects 中找到了这个:

flush() 不一定将文件的数据写入磁盘。使用flush() 后跟os.fsync() 来确保这种行为。

所以我的问题是:Python 的 flush 到底在做什么?我以为它会强制将数据写入磁盘,但现在我发现它没有。为什么?

【问题讨论】:

【参考方案1】:

通常涉及两个级别的缓冲:

    内部缓冲区 操作系统缓冲区

内部缓冲区是由您正在编程的运行时/库/语言创建的缓冲区,旨在通过避免每次写入的系统调用来加快处理速度。相反,当您写入文件对象时,您会写入其缓冲区,并且每当缓冲区填满时,数据就会使用系统调用写入实际文件。

但是,由于操作系统缓冲区的原因,这可能并不意味着数据已写入磁盘。这可能只是意味着数据从运行时维护的缓冲区复制到操作系统维护的缓冲区中。

如果你写了一些东西,它最终进入了缓冲区(仅),并且你的机器断电了,当机器关闭时,这些数据不在磁盘上。

所以,为了帮助解决这个问题,您可以在它们各自的对象上使用 flushfsync 方法。

第一个,flush,将简单地将任何滞留在程序缓冲区中的数据写入实际文件。通常这意味着数据将从程序缓冲区复制到操作系统缓冲区。

具体而言,这意味着如果另一个进程打开了相同的文件以供读取,它将能够访问您刚刚刷新到文件中的数据。但是,这并不一定意味着它已经“永久”存储在磁盘上。

为此,您需要调用os.fsync 方法,该方法确保所有操作系统缓冲区与它们所针对的存储设备同步,换句话说,该方法会将数据从操作系统缓冲区复制到磁盘.

通常您不需要为这两种方法而烦恼,但如果您处于对实际最终存储在磁盘上的内容的妄想症是一件好事的情况下,您应该按照说明进行这两个调用。


2018 年的附录。

请注意,具有缓存机制的磁盘现在比 2013 年更加普遍,因此现在涉及到更多级别的缓存和缓冲区。我假设这些缓冲区也将由同步/刷新调用处理,但我真的不知道。

【讨论】:

当我使用with file('blah') as fd: #dostuff 构造时,我知道它保证关闭文件描述符。它是否也刷新或同步? @Marcin:它刷新,但不同步。 fsync 是原子性所必需的。您不能期望关闭文件,重新打开它并在中间没有fsync 的情况下找到您的内容。它通常可以工作,但它不适用于具有 ext4 和默认挂载选项的 Linux。此外,fsync 也不能保证真的用磁铁翻转盘片上的铁,因为 1:fsync 可以禁用(通过笔记本电脑模式),2:硬盘内部缓冲可能不会被指示刷新。 如果文件是由另一个进程写入的,是否有办法刷新操作系统的所有文件的缓冲区? fsync 相对昂贵。通常,您不会编写需要 100% ACID 合规性和持久性以进行磁盘访问的任务关键型软件,如果您这样做了,您可能会痛苦地意识到这一点,并且应该知道您可以采取哪些步骤来获得这些保证.调用 fsync 将等待物理磁盘访问发生以将数据写入磁盘,而刷新和关闭将仅等待数据移动到缓存内存。速度差异大概是几个数量级。【参考方案2】:

因为操作系统可能不会这样做。刷新操作强制文件数据进入 RAM 中的文件缓存,然后操作系统的工作就是从那里实际将其发送到磁盘。

【讨论】:

你是对的,但actually 在这里是相对的:如果目标设备启用了写入缓存,当os.fsync() 返回时,数据可能还没有到达实际的盘片/芯片。【参考方案3】:

它会刷新内部缓冲区,这应该会导致操作系统将缓冲区写出到文件中。[1] Python 使用操作系统的默认缓冲,除非您另外配置。

但有时操作系统仍然选择不合作。尤其是像 Windows/NTFS 中的写延迟这样美妙的事情。基本上内部缓冲区已被刷新,但操作系统缓冲区仍在保留它。因此,在这些情况下,您必须告诉操作系统使用os.fsync() 将其写入磁盘。

[1]http://docs.python.org/library/stdtypes.html

【讨论】:

【参考方案4】:

基本上,flush() 会清除您的 RAM 缓冲区,它的真正威力在于它可以让您在之后继续写入它 - 但它不应该被认为是最好/最安全的写入文件功能。它正在刷新您的 RAM 以获取更多数据,仅此而已。如果您想确保数据被安全地写入文件,请改用 close() 。

【讨论】:

以上是关于file.flush() 到底在做啥?的主要内容,如果未能解决你的问题,请参考以下文章

Three.js raycaster 到底在做啥?

-fno-builtin 到底在做啥?

Python 多处理模块的 .join() 方法到底在做啥?

MySQL在做啥??启动时 100% 的磁盘利用率

这个条件运算符是做啥的? [复制]

文件file