【问题标题】:Ensuring completenes of file writes on Linux ext4 file system确保 Linux ext4 文件系统上文件写入的完整性
【发布时间】:2021-12-16 06:07:25
【问题描述】:

我们的(嵌入式)Linux 系统有一个 ext4 文件系统。现在,我们的其中一个应用程序需要使用简单的文件写入 API 修改数据文件。那里的要求是文件更新应该是原子的 - 不是来自不同应用程序的并行写入(我们没有那个),而是在断电的情况下每个写入都不能部分执行的意义上- 它可以完全执行,也可以不执行。这是有保证的吗?我知道文件写入可能不会因为缓存而立即执行,但我不确定这些写入是否可以被缓存分割成部分的方式,因此我的问题是。

我也可以使用 copy-write-rename 方法将原始文件复制到临时文件,在那里进行更改,然后将文件重命名回原始文件,这取决于重命名操作的原子性质。但即便如此,我也不确定这些操作能否保证按照我想要的方式进行排序(尤其是写入和重命名)。

【问题讨论】:

  • 数据丢失时会发生什么。嵌入式系统对生命至关重要(例如某些医院设备?)
  • 数据丢失时(在现实世界中)会发生什么?您的嵌入式系统是消费级吸尘器(数据丢失很烦人,但并不重要)还是神经外科机器人((数据丢失会导致人员死亡)?
  • 那里的数据丢失并不重要。产品有点像路由器。
  • 编辑您的问题以改进它。我觉得我的回答很中肯。随意点赞。但是你想要一个保证,你不能得到它。与您的老板或客户讨论。考虑改进硬件或降低规格。
  • AFAIK 是的,写入可以是非原子的。例如,假设您的写入跨越页面缓存中的两个页面。期望内核记住它们必须一起刷新或以特定顺序刷新是不合理的。如果硬件一次只能写出一页或一个扇区,那么刷新甚至可能是不可能的。几乎确定磁盘上内容的唯一方法是使用fsync

标签: linux filesystems atomic ext4


【解决方案1】:

可能会使用(在您的用户模式应用程序中)sync(2) 系统调用。在此之前,如果使用stdio,请使用fflush(3)

为确保原子性,您可能需要使用Frama-CBismonDECODER 项目等静态分析工具检查大量代码(甚至可能在内核内部)。当然,这是非常昂贵的(2021 年超过 10 万欧元或美元)。请随时通过电子邮件与我联系。请注意Rice's theorem

在内核(或硬件)级别,原子性无法保证:例如,成功的 4 兆字节的write(2) 系统调用(由您的应用程序)很可能涉及(在连接到硬盘的SATA 电缆上) 许多帧或数据包。如果断电,数据就会丢失。

不要忘记 Linux kernelGNU libc 是开源的。您可以研究他们的源代码并进行改进。

还可以考虑一种硬件方法:添加一些UPS

另一种可能性是扩展您的 C 编译器,例如编码您的GCC plugin,以半自动添加对sync(2)的调用

另一种可能性是generate your C code(例如,使用RefPerSysGPP 或您自己的C 代码生成器)。 Jacques Pitrat 的最后一本书 Artificial Beings, the conscious of a conscious machine 详细解释了如何做到这一点。

另请参阅my sync-periodically.c program(GPLv3+ 许可;因此无保修)。

您还可以改进一些生成 C 的开源编译器(例如 Bigloo),以便在合适的位置发出对 sync(2) 的调用。

PS。如果您的嵌入式软件是多线程的(使用多个 pthread 或进程),或者如果您的硬件有多个磁盘或 SSD,或者在太空中(宇宙射线?)或在核发电站(放射性?)

【讨论】:

  • 感谢所有建议,但这不是我的意思。即使我自动同步/刷新(并且我可以在编写后在我的应用程序中进行),这仍然可能会因电源故障而中断。我同意。我唯一需要知道的是我是否可以确保写入是否完全提交,而不是部分提交。硬件 UPS 不是一种选择(它不是我们的硬件)。多线程在这里也不是问题。
猜你喜欢
  • 1970-01-01
  • 2012-04-27
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
  • 2021-09-19
  • 1970-01-01
  • 2020-01-19
  • 2015-05-08
相关资源
最近更新 更多