是否在所有文件系统上按顺序写入没有查找刷新字节的文件?

Does writing to a file with no seeks flush bytes sequentially on all file systems?

我正在编写 JSON 个文件。这意味着对于每个 '{' 个字符,都有一个对应的 '}' 并且文件中的最后一个字节是 '}'。写入顺序发生。没有 fseeks。因此,如果写入文件以某种方式中断,我预计会有一个无效的 JSON 文件。

现在一个假设的文件系统可能决定乱序刷新我的字节。这意味着如果在写入期间发生断电,在刷新所有内容之前,我可以获得一个有效的 JSON,其中不包含我想要的数据。我可以使用字符串 "xxx",而不是 "yyy",或者数字末尾缺少数字。

有这样的文件系统吗?我可以相信如果一个文件是有效的,那么它就一定是完整的吗?

编辑:这个问题是针对如果数据丢失最后一个字节则数据无效的情况。 JSON 在这里是说明性的。技术上 42342 是有效的 JSON,如果不完整则无法验证。

文件系统可能会乱序刷新页面的原因有多种:

  • 该页面有来自 2 个文件的数据,另一个文件正在刷新到磁盘。
  • 该页面在进程的工作集之外(因此不值得缓存)并且 OS 需要内存用于其他目的。
  • 文件系统是分布式的,例如OrangeFS 或 Andrew 文件系统,并按照非常不同的实现规则进行播放。
  • 文件系统 NFS 面向更复杂的分布式异构设备集,其中一些写入是完全同步的,应用程序 none 更明智。

不仅是文件系统,还有底层设备。

  • 块设备可能会进行缓冲,直到文件系统实际需要完全刷新,并以它认为合适的顺序刷新它(因为它不知道文件的概念)。
  • 块设备可以条带化 (RAID 0),这样一个设备可以先于另一个设备刷新。

也就是说,崩溃后像 xxx 这样丢失 3 个字节的情况极不可能发生。它更有可能经历块丢失,例如4096 字节的倍数。

事实是,大多数文件系统对崩溃期间写入的数据(与元数据相反)的完整性几乎没有保证。

当需要原子性时,应用程序通常做的是利用 rename(2) 或其等价物:

  1. 写入临时文件,例如POSIX write(2).
  2. 刷新文件,例如使用 POSIX fsync(2) 并关闭它。
  3. 将文件重命名为目标名称,例如POSIX rename(2).

我知道所有正在使用的 POSIX 文件系统都以崩溃安全的方式实现 POSIX 重命名,我假设 NTFS 也是如此。

但这显然不是 POSIX 严格要求的。由于您正在编写新文件,所以这不是什么大问题,但如果您想更加偏执,您可以添加另一个步骤:

  1. 删除临时文件(不存在则忽略错误)