因此,我的应用程序通常希望保存文件以便以后再次加载。最近因崩溃而不幸,我想以这样的方式编写操作,以确保我拥有新数据或原始数据,但没有损坏的混乱。
我的第一个想法是做一些事情(保存名为example.dat的文件):
然后在加载时,应用程序可以遵循以下规则:
然而,经过一些研究,我发现除了操作系统缓存,我可以用文件刷新方法覆盖,一些磁盘驱动器仍然在内部缓存,甚至可能骗到操作系统说它们已完成,所以4.可以完成,写入实际上没有写入,如果系统出现故障,我丢失了数据......
我不确定磁盘问题是否可以由应用程序解决,但是正确的规则是否正确?我应该保留文件的旧恢复副本以确保更长时间,有关此类事项的准则是什么(例如,可接受的磁盘使用情况,用户应该选择,放置此类文件的位置等)。
另外,我应该如何避免用户和“example.dat.tmp”的其他程序发生潜在冲突。我记得有时候从其他软件看到“~example.dat”,这是一个更好的约定吗?
答案 0 :(得分:2)
如果磁盘驱动器向操作系统报告该数据 物理上在磁盘上,但事实并非如此,那么你就不多了 可以做到这一点。很多磁盘都会缓存一定数量的磁盘 写,并报告他们完成,但 应该 电池备份,无论如何都完成物理写入 (并且在系统崩溃的情况下,他们不会丢失数据,因为他们 甚至都不会看到它。
对于其他人,你说你做过一些研究,所以毫无疑问
知道你不能使用std::ofstream
(也不是FILE*
);
你必须在系统级别进行实际写入,然后打开
具有特殊属性的文件,以确保完整
同步。否则,操作可以留在
操作系统缓冲了一段时间。而据我所知,
没有办法确保rename
的这种同步。
(但我不确定这是否必要,如果你总是保留两个
版本:在这种情况下,我通常的惯例是写入
文件"example.dat.new"
,然后当我写完时,删除
任何名为"example.dat.bak"
的文件,将"example.dat"
重命名为
"example.dat.bak"
,然后将"example.dat.new"
重命名为
"example.dat"
。鉴于此,你应该能够弄清楚
发生了什么或没发生过,找到了正确的文件
(交互式地,如果需要,或插入初始线与
时间戳)。
答案 1 :(得分:0)
如果有可能在不同的进程可能通过您描述的相同协议时,您应该在编写替换时锁定实际数据文件。
您可以使用flock
进行文件锁定。
至于你的临时文件名,你可以将你的进程ID作为其中的一部分,例如“example.dat.3124”,没有其他同时运行的进程会生成相同的名称。