如何重现由于未刷新内核缓冲区而导致的数据丢失?

问题描述 投票:0回答:1

我最近在 Linux 开发环境中遇到了一个问题。我编写了一个函数,通过单击按钮触发将结果导出到 Excel 文件。该函数执行后,它会刷新用户空间缓冲区并显示“成功”对话框。但是,如果用户过快地移除 USB 驱动器,即使出现该对话框,文件也不会保存到该驱动器。

我理解发生这种情况是因为数据仍在内核缓冲区中并且尚未写入硬件。我使用

fsync
解决了这个问题。

现在,我想系统地测试并重现这个问题。最好的方法是什么?

我尝试了各种方法,例如在写入功能完成后立即执行断开 USB 驱动器的命令以及其他操作。我什至尝试手动执行此操作,但无法重现该问题。

我知道这个问题与内核缓冲区有关,但我找不到一个简单的例子来有效地重现它,这非常令人沮丧。

linux ubuntu x86-64 buffer fsync
1个回答
0
投票

我解决了。我可以在虚拟机中进行操作,执行它并停止它,无需

fsync

以下是更改测试的方法:

#include <iostream>
#include <filesystem>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

void sync_file_with_fsync(const std::filesystem::path& dest_path) {
    int fd = open(dest_path.c_str(), O_WRONLY);
    if (fd == -1) {
        std::cerr << "无法打开文件进行 fsync: " << strerror(errno) << std::endl;
        return;
    }

    if (fsync(fd) == -1) {
        std::cerr << "fsync 失败: " << strerror(errno) << std::endl;
    } else {
        std::cout << "fsync 成功,数据已写入磁盘。" << std::endl;
    }
    close(fd);
}

int main(){
    std::filesystem::path source_path = "/home/mq-b/test/test_fsync/1MB_file.dat";
    std::filesystem::path dest_path = "/media/mq-b/MQ-B/1MB_file.dat";
    std::filesystem::copy_file(source_path, dest_path, std::filesystem::copy_options::overwrite_existing);

    sync_file_with_fsync(dest_path);

    std::clog << dest_path << " 文件复制完成,大小:" << std::filesystem::file_size(dest_path) << " Byte" << std::endl;
}
© www.soinside.com 2019 - 2024. All rights reserved.