如何确保数据写入物理介质?

问题描述

我有一个由脚本调用的程序。该程序将大量数据写入磁盘上的文件,然后终止。一旦运行完成,脚本就会切断整个系统的电源。

我遇到的问题是文件没有完整写入。如果它是一个 4GiB 文件,那么当我稍后查看它时,磁盘上实际上只有大约 2GiB。我能够可靠地确保所有数据都被写入的唯一方法是在退出之前让程序休眠一小段时间,但这是一个非常糟糕且不可靠的黑客,我不想使用。以下是我最近尝试涉及的一些示例代码:

int main () {
    FILE *output;
    output = fopen("/logs/data","w");

    [fwrite several GiB of data to output]

    fflush(output);

    int fdo = open("/logs",O_RDONLY);
    fsync(fdo);

    fclose(output);
    close(fdo);

    return 0;
}

我最初尝试使用文件描述符构建我的 FILE 并在使用的描述符 (/logs/data) 上调用 fsync() 但是这产生了同样的问题。根据 fsync(2) 的规范:

调用 fsync() 不一定确保 包含该文件的目录也已到达磁盘。为此,一个 目录的文件描述符上的显式 fsync() 也是 需要。

这让我找到了上面的代码,为包含我的数据文件的目录创建了一个特定的文件描述符,并在其上调用 fsync()。然而结果是一样的。我真的不明白为什么会发生这种情况,因为 fsync() 应该是阻塞的:

调用阻塞,直到 设备报告传输已完成。

另外,正如你所看到的,我在 FILE 上添加了一个 fflush() 认为可能 fsync() 只是同步以前的数据被刷新,但这对情况没有任何影响。

在结束程序之前,我需要以某种方式验证数据实际上已写入物理介质,但我不知道该怎么做。我看到有一些文件,例如 /sys/block/[device]/[partition]/stat 可以告诉我还有多少脏块要写入,我可以等待该值达到 0 但这不会似乎是解决应该是一个简单问题的好方法,此外,如果有任何其他程序在磁盘上运行,那么我不想等待他们同步他们的数据,因为我只关心完整性这个特定文件和 stat 文件没有区别。

编辑 根据建议,我尝试 fsync() 两次,首先是文件,然后是目录:

int main () {
    FILE *output;
    int fd = open("/logs/data",O_WRONLY | O_CREAT,660);
    output = fdopen(fd,"w");

    [fwrite several GiB of data to output]

    fsync(fd);
    int fdo = open("/logs",O_RDONLY);
    fsync(fdo);

    fclose(output);
    close(fd);
    close(fdo);

    return 0;
}

这产生了一些有趣的输出。对于 4GiB(4294967296 字节)文件,磁盘上的实际数据大小为 4294963200,恰好与总值相差 1 个页面文件(4096 字节)。它似乎非常接近一个可行的解决方案,但它仍然不能保证每个字节的数据。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)