快速文件复制与进度

时间:2010-10-09 03:50:35

标签: c++ file copy sdl performance

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

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

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:4)

不要使用复制进度同步更新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

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

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