【问题标题】:Fast file copy with progress有进度的快速文件复制
【发布时间】:2010-10-09 03:50:34
【问题描述】:

我正在为 Linux 编写一个 SDL 应用程序,它可以在控制台(没有 X 服务器)上运行。我拥有的一个功能是文件复制机制,它将特定文件从 HDD 复制到 USB 闪存设备,并在 UI 中显示此复制的进度。为此,我使用简单的 while 循环并按 8kB 块复制文件来获得复制进度。问题是,它很慢。我要在将近 10 分钟内复制一个 100 MB 的文件,这是不可接受的。

如何实现更快的文件复制?我正在考虑一些异步 API,它将文件从 HDD 读取到缓冲区并将数据存储到 USB 中的单独线程中,但我不知道我是否应该自己实现它,因为它看起来并不容易。也许你知道一些对我有用的 C++ API/库?或者其他更好的方法?

【问题讨论】:

  • "我正在使用简单的 while 循环并按 8kB 块复制文件以获得复制进度。" - 这类似于标准cp 的工作方式。你确定没有其他东西让你慢下来吗?您确定您的 USB 驱动器没有 sync 挂载选项吗? Linux 针对这种情况进行了优化,10 分钟 100MB - 你的问题不在于操作系统,而在于你自己的应用程序。

标签: c++ file copy sdl performance


【解决方案1】:

不要与复制进度同步更新您的 UI,这会大大减慢速度。您应该在与主 UI 线程不同的线程上运行文件副本,以便文件副本可以尽可能快地进行,而不会妨碍应用程序的响应能力。然后,UI 可以以自然速率(例如,以显示器的刷新率)自我更新。

您还应该使用大于 8 KB 的缓冲区大小。尝试一下,但我认为使用更大的缓冲区(例如,在 64-128 KB 范围内)可以获得更快的结果。

所以,它可能看起来像这样:

#define BUFSIZE (64*1024)

volatile off_t progress, max_progress;

void *thread_proc(void *arg)
{
    // Error checking omitted for expository purposes
    char buffer[BUFSIZE];
    int in = open("source_file", O_RDONLY);
    int out = open("destination_file", O_WRONLY | O_CREAT | O_TRUNC);

    // Get the input file size
    struct stat st;
    fstat(in, &st);

    progress = 0;
    max_progress = st.st_size;

    ssize_t bytes_read;
    while((bytes_read = read(in, buffer, BUFSIZE)) > 0)
    {
        write(out, buffer, BUFSIZE);
        progress += bytes_read;
    }

    // copy is done, or an error occurred
    close(in);
    close(out);

    return 0;
}

void start_file_copy()
{
    pthread_t t;
    pthread_create(&t, NULL, &thread_proc, 0);
}

// In your UI thread's repaint handler, use the values of progress and
// max_progress

请注意,如果您将文件发送到 socket 而不是另一个文件,则应改用 sendfile(2) 系统调用,它将文件直接复制到内核空间中,而无需往返用户空间。当然,如果这样做,您将无法获得任何进度信息,因此可能并不总是理想的。

对于 Windows 系统,您应该使用CopyFileEx,它既高效又为您提供进度回调例程。

【讨论】:

    【解决方案2】:

    让操作系统完成所有工作:

    1. 将文件映射到内存:mmap,将大大加快读取过程。
    2. 使用msync将其保存到文件中。

    【讨论】:

      猜你喜欢
      • 2016-03-12
      • 2011-12-15
      • 2018-07-04
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多