我写了一个程序,将两个小文件压缩成一个更大的文件。我首先从输入文件读取数据,合并数据,并将输出写入临时文件。完成后,我将临时文件重命名为所需的文件名(位于磁盘上的同一分区中)。这是伪代码:
FILE* fp_1 = fopen("file_1.dat", "r+b");
FILE* fp_2 = fopen("file_2.dat", "r+b");
FILE* fp_out = fopen("file_tmp.dat", "w+b");
// 1. Read data for the key in two files
const char* data_1 = ...;
const char* data_2 = ...;
// 2. Merge data, store in an allocated buffer
// 3. Write merged buffer to temp file
fwrite(temp_buff, estimated_size, 1, fp_out);
fflush(fp_out);
fclose(fp_1);
fclose(fp_2);
fclose(fp_out);
// Now rename temp file to desired file name
if(std::rename("file_tmp.dat", "file_out.dat") == 0)
{
std::remove("file_1.dat");
std::remove("file_2.dat");
}
我用两个5 MB的输入文件反复测试程序。有一次我通过拔掉电源线突然关闭了系统。重新启动系统后,我检查了数据,发现输入文件已被删除,file_out.dat
填充了所有零。这让我相信系统在删除了2个输入文件之后立即关闭,输出数据仍在磁盘控制器缓冲区中的某个位置。如果这是真的,那么有什么方法可以检查数据是否已实际写入磁盘?
答案 0 :(得分:5)
不是一般情况。磁盘可以骗到操作系统,声称写入完成时,它实际上只是在硬盘驱动器的板载RAM缓存中排队,这将在突然断电时丢失。
您可以做的最好的事情就是明确要求操作系统在您执行fflush
之后告诉磁盘“真正地,真正地同步所有内容”,使用fsync
限制范围或使用类似的内容sync
or syncfs
(前者同步所有文件系统,后者将范围限制为对应于单个文件描述符的文件系统)。您希望在最终fsync
之后但在fflush
之前和/或rename
/ sync
后syncfs
之后执行定位rename
remove
1}}但在mainVC
调用之前,所以在删除源文件之前,数据和文件系统表肯定会更新。
当然,就像我说的,这是最好的努力;如果磁盘控制器正在向操作系统说谎,那么你就无法为磁盘编写新的固件和驱动程序,这可能太过分了。