原子文件修改

and*_*dll 6 java unix windows

我想覆盖文件中的区域(可能很小).假设我调用fseek,fwrite,fsync.有没有办法确保这种区域重写操作的原子性,例如,我需要确定,在任何情况下失败,该区域将只包含旧的(修改前)数据,或仅包含新的(修改的)数据,但不包括混合这个.

我想强调两件事.

第一:没有办法原子地写任何大小的区域是可以的 - 我们可以通过将数据附加到文件,fsync'ing,然后重写文件中的'指针'区域来处理它,然后再次fsyncing.但是,如果'指针'写入不是原子的,我们仍然可以使用非法指针来破坏文件.

第二:我很确定,写1字节区域是原子的:我不会在文件中看到任何从未放在那里的字节.因此我们可以使用一些技巧为地址分配两个区域并使用1字节开关,因此重写区域变为 - 附加新数据,同步,重写两个(未使用的)指针槽中的一个,再次同步,然后重写'切换字节'并再次同步.因此,覆盖区域操作现在至少包含3个fsync调用.

所有这一切都会更加轻松,如果我有长时间的原子写作,但我真的拥有它吗?

有没有办法在不使用第2点中提到的方法的情况下处理这种情况?

另一个问题是 - 写作和同步之间是否有任何顺序保证?例如,如果我调用fseek,fwrite [1],fseek,fwrite [2],fsync,我可以在[2]提交写入,并在[1]写入 - 不提交吗?

这个问题适用于linux和windows操作系统,任何特定的答案(例如在ubuntu版本中都是abc ....)也是需要的.

Dra*_*sha 1

通常可以安全地假设写入 512 字节块是由 HDD 在一次写入中完成的。但是,我不会这样认为。相反,我会采用您的第二个解决方案,同时在您的写入中添加校验和并在更改文件中的指针之前对其进行验证。

通常,向写入磁盘的所有内容添加校验和是一个好习惯。

要回答有关“同步”保证的问题 - 您可以假设这一点。虽然同步依赖于文件系统和磁盘,但假设我们正在讨论“合理”的实现。

  • 在第一次之后,sync数据保证被刷新到磁盘(磁盘可能仍然在其缓存中),并且如果数据您期望获得您写入的任何内容。
  • 如果第二次之后sync两次同步的数据都在磁盘缓存中,则可能会发生您所描述的情况,但恕我直言,这种可能性非常低。

无论如何,没有其他机制可以保证数据位于磁盘上。这就是为什么你必须有校验和

更多信息:确保 fsync 完成其工作