7

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

我想强调两件事。

首先:如果没有办法以原子方式写入任何大小的区域也没关系 - 我们可以通过将数据附加到文件中来处理它,fsync'ing,然后重写文件中的“指针”区域,然后再次 fsync。但是,如果“指针”写入不是原子的,我们仍然可以使用非法指针损坏文件。

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

所有这一切都会容易得多,如果我将有很长的原子写作,但我真的有吗?

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

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

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

4

1 回答 1

1

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

通常,将校验和添加到写入磁盘的所有内容中是一个很好的做法。

要回答“同步”保证 - 你可以假设。虽然同步是 FS 和磁盘相关的,但假设我们正在谈论“合理”的实现。

  • 在第一次之后sync,数据保证被刷新到磁盘(磁盘可能仍然在它的缓存中),如果数据你应该得到你写的任何东西。
  • 如果第二次之后sync两个同步的数据都在磁盘缓存中,那么您描述的情况可能会发生,但恕我直言,这种可能性非常低。

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

更多信息:确保 fsync 完成了它的工作

于 2012-09-04T17:52:35.253 回答