2013-01-21 19 views
2

考虑这个例子:是“文件数据”和“文件大小”提交到磁盘一起或单独

FILE* stream = fopen("my_file", "w"); 
fputs("hello", stream); 

如果电源的fputs的执行(过程中丢失会发生什么)?

之后,我能否找到非零大小的“my_file”,但第一个字节不是'h'? 如果是,它保证为零,还是可以包含任意值?

当然,假设没有其他人触摸我们的文件。

编辑:还假定目标磁盘驱动器/设备是能够保持足够长的时间足以写入所有已在内部缓冲的数据的类型。

POSIX对此有什么要说的吗? Linux? Windows?

编辑:我不打算专注于如何实现STDIO流API的细节。假设POSIX,这里是我真正的意思是:

int fd = open("my_file", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); 
write(fd, "hello", 5); 

编辑:POSIX认为大小为文件元数据,因此问题很可能被改写为:可以将文件数据和元数据,该文件作为上述代码的结果,它们会在不同的阶段被提交到磁盘上?

编辑:http://www.sqlite.org/atomiccommit.html发现这一点:

7.5文件系统具有安全附加语义

在SQLite的版本中引入的另一个优化3.5.0利用的基本盘的“安全附加”行为 。回想一下, SQLite假定当数据被附加到文件(特别是回滚日志的 )时,首先增加文件大小 ,并且内容被写入第二个。因此,如果在文件大小增加但写入内容为 之前电源丢失 ,则文件将保留包含无效的“垃圾”数据。但是,VFS的xDeviceCharacteristics方法可能会指示 文件系统实现“安全附加”语义。此 表示在文件大小增加 之前写入内容,以便在断电或系统崩溃时无法将 引入回滚日志。

这似乎提供了至少部分答案。

+1

[SQLite如何处理原子提交](http://www.sqlite.org/ atomiccommit.html)可能是有趣的。 – user786653

+0

良好的链接 - 谢谢! –

回答

1

对于linux,写入缓冲区的内容不保证写入磁盘immediatley。

kernel复制databuffer,后来在后台,内核收集了所有的dirty buffers的,最好将它们排序,并写出来,以disk。这就是writeback。这可以使写入调用快速发生,几乎立即返回。它也允许内核defer writes更多idle periods和批量许多writes together

+0

好的信息,但我的问题是具体关于一个文件可能最终从零增加,但其内容从未写入,例如,由于电源故障。我想这个问题的答案与内核如何执行这个“writeback”过程的复杂细节有很大关系。我希望,例如,POSIX在这方面确实提出了一些保证。 –

0

这在很大程度上取决于所使用的文件系统(ext3ext4xfs,....),并给它安装时的选项,所以不容易的一刀切,所有的答案。也许如果你告诉我们你的/etc/fstab并告诉我们你想知道哪个文件系统,可以给出更好的答案...

+0

如果可能,我宁愿不考虑特定文件系统的细节。我将不得不假定它可以是任何流行的。但是我想你所说的是,对于某些文件系统,确实可以找到非零大小的“my_file”,但在断电后第一个字节不是“h”。例如,如果您有任何详细信息可以提供'ext4',那就太好了。 –

相关问题