flush()函数不一定将文件数据写入磁盘。使用flush()
后跟os.fsync()
可以确保此行为。
flush
究竟是做什么的?我原以为它会强制将数据写入磁盘,但现在看来它并没有这样做。为什么呢?flush()函数不一定将文件数据写入磁盘。使用flush()
后跟os.fsync()
可以确保此行为。
flush
究竟是做什么的?我原以为它会强制将数据写入磁盘,但现在看来它并没有这样做。为什么呢?通常情况下,涉及两个级别的缓冲:
内部缓冲是由您所编写程序所使用的运行时/库/语言创建的缓冲区,旨在通过避免每次写入都进行系统调用来加速处理速度。因此,当您向文件对象写入内容时,实际上是将其写入缓冲区中,只有当缓冲区被填满时,才会使用系统调用将数据写入实际文件。
然而,由于操作系统缓冲的存在,这并不意味着数据已被写入磁盘。它可能只是从您运行时维护的缓冲区复制到操作系统维护的缓冲区。
如果您写入的内容仅停留在缓冲区中,当您的计算机断电时,该数据将不会保存到磁盘上。
因此,为了解决这个问题,您需要对相应对象使用flush
和fsync
方法。
其中,flush
方法将简单地将任何滞留在程序缓冲区中的数据写入实际文件。通常意味着数据将从程序缓冲区复制到操作系统缓冲区。
具体来说,这意味着如果另一个进程正在读取同一文件,它将能够访问您刚刚将数据刷新到文件中。然而,这并不一定意味着数据已经被"永久"存储在磁盘上。
为了实现这一点,您需要调用os.fsync
方法,该方法确保所有操作系统缓冲区与其所属的存储设备进行同步,换句话说,该方法将把数据从操作系统缓冲区复制到磁盘。
通常情况下,您不需要使用任何一种方法,但是如果您担心什么内容实际上已经保存到磁盘上,那么请按照说明调用两个方法。
2018年补充说明。
请注意,带有缓存机制的磁盘现在比2013年更常见,因此现在涉及的缓存和缓冲区级别更多。我 假设 这些缓冲区也将由同步/刷新调用处理,但我不太确定。
由于操作系统可能不会这样做,所以需要执行刷新操作。刷新操作将文件数据强制写入到RAM中的文件缓存中,然后由操作系统实际将其发送到磁盘。
os.fsync()
返回时,数据可能还没有到达实际的盘片/芯片。 - Frédéric Hamidios.fsync()
告诉操作系统将其写入磁盘。基本上,flush() 函数可以清空你的 RAM 缓冲区,它的真正作用在于让你在后面继续向缓冲区写入数据 - 但不应该认为这是最好/最安全的写入文件功能。它只是为了让更多的数据进来而清空你的 RAM 缓冲区而已。如果你确保数据被安全地写入文件,那么就应该使用 close() 函数。
with file('blah') as fd: #dostuff
结构时,我知道它保证关闭文件描述符。那么它是否也会刷新或同步? - Marcinfsync
对于原子性是必要的。如果没有在关闭文件、重新打开文件之前加入fsync
,你不能指望找到你的内容。尽管它通常有效,但在使用linux系统的ext4文件系统和默认挂载选项时并不总是有效。另外,fsync
不能保证真正磁铁翻转盘片,因为1:fsync
可以被禁用(通过笔记本电脑模式),2:硬盘内部缓存可能没有被要求刷新。 - v.oddou