![在嵌入式环境中同步还是不同步?](https://linux22.com/image/159803/%E5%9C%A8%E5%B5%8C%E5%85%A5%E5%BC%8F%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%90%8C%E6%AD%A5%E8%BF%98%E6%98%AF%E4%B8%8D%E5%90%8C%E6%AD%A5%EF%BC%9F.png)
我有一个单板设备,在一块闪存上运行 Debian 10。使用 UBIFS,并将其分为两个卷:一个 ro root 和一个 rw /var。我发现在电源循环/重置条件下,我最终会得到 0 字节文件。我将“设置”保存在 /var/opt/myApp 中。更改 /var 的挂载选项以包含sync
似乎可以使这些事件消失。
我知道通常的建议是异步优于同步,但通常会用“通常,但并非总是”进行警告,几乎没有解释可能的例外情况。
另一种解决方案是修改我将数据写入磁盘的所有调用站点,不仅在文件关闭时刷新,而且还同步(我用 python 做了很多)。从编码/完整性的角度来看,安装似乎sync
既减少了工作量,又避免了我错过在某些地方添加同步保护的情况,因为它是通用的。
此外,我允许设备将数据保存到 USB 拇指驱动器。我认为我也应该安装这些同步,以减少在数据写入后立即将其拉出时的损失。
这是一个适当的特殊配置来证明使用的合理性吗sync
?或者我应该使用替代解决方案?
答案1
这是我的观点:抱歉提前啰嗦。
当我们具体谈论时,ubifs
我们应该始终选择其中一个sync
/类似的选项。
ubifs
支持write-back caching
这意味着写入文件的更改不会直接写入闪存。它们首先存储在页面缓存中,然后写入闪存。 (阅读write buffers
有关 UBIFS 中 NAND 闪存的更多信息)
这通过减少写入次数来提高文件系统性能。
请注意,这是asynchronous
fs 的行为。
正如你在问题中所说的那样,当你使用 -sync 选项挂载 UBIFS 时,它将创建文件系统synchronous
(每次都将更改写入闪存),但是以性能下降为代价。
如果您使用asynchronous
像 ubifs 这样的文件系统,那么确保写入写入闪存的责任就落在应用程序开发人员身上。这是 write(2) 的手册页内容:
$ man 2 write
NOTES
A successful return from write() does not make any guarantee that data
has been committed to disk. In fact, on some buggy implementations, it
does not even guarantee that space has successfully been reserved for
the data. The only way to be sure is to call fsync(2) after you are
done writing all your data.
使用
sync
- 同步整个文件系统。可能不是最佳的
fsync
- 主要完成工作
fdatasync
- 仅刷新数据更改,而不刷新元数据(权限)。比可能更优化fsync
(不确定)
另请阅读关于 fsync 的好文章
所以最后,你的选择:
- 使用“同步”挂载 - 性能受到影响
- 使用上述选项改进应用程序
sync
。 - 在应用程序中处理 0 字节文件
- 创建临时文件并稍后重命名
最后一个想法,可能想切换到同步文件系统jffs2
(如果使用 NAND 闪存,则不是完全同步)。我知道这不是你问题的答案,但是呃,写了这么多还不如写这个......