使用内存映射文件读取大文件

我看到很多文章build议不要将大文件映射为mmap文件,这样虚拟地址空间将不会被mmap完全占用。

如何改变64位进程的地址空间大幅增加? 如果我需要随机访问一个文件,是否有一个原因不要一次映射整个文件? (几十个GB文件)

在64位上,继续并映射文件。

有一件事要考虑,基于Linux的经验:如果访问是真正的随机,并且文件比你期望缓存RAM(因此再次击中页面的机会很小) MADV_RANDOM ,那么值得指定MADV_RANDOM 疯狂地停止积累的打文件页稳步和毫无意义地交换其他有用的东西了。 不知道什么窗口等效的API虽然。

有一个原因要考虑使用内存映射文件,即使在64位平台上(虚拟地址空间的大小不是问题)。 它涉及(潜在的)错误处理。

当“常规”读取文件时,任何I / O错误都由相应的函数返回值报告。 其余的错误处理由您决定。

OTOH如果在隐式I / O期间出现错误(由页错误产生,并尝试将所需的文件部分加载到适当的内存页中) – 错误处理机制取决于操作系统。

在Windows中,错误处理是通过SEH执行的 – 所谓的“结构化异常处理”。 异常传播到用户模式(应用程序的代码),你有机会正确处理它。 正确的处理要求在编译器中编译适当的异常处理设置(以保证析构函数的调用,如果适用的话)。

我不知道如何在unix / linux中执行错误处理。

PS我不说没有使用内存映射文件。 我说这样小心

有一点需要注意的是,映射创建时,内存映射需要大量连续的(虚拟)内存块; 在32位系统上,这特别糟糕,因为在一个加载的系统上,不太可能长时间运行连续的ram,映射将失败。 在64位系统上这是非常容易的,因为64位的上限是巨大的。

如果您在受控环境下运行代码(例如,您正在构建自己的64位服务器环境,并知道运行此代码就好了),请继续并映射整个文件并进行处理。

如果您正在尝试编写通用代码,这些代码可以运行在任意数量的配置类型的软件上,那么您需要坚持使用更小的分块映射策略。 例如,将大文件映射到1GB块的集合,并具有一个抽象层,在执行操作之前,抽象层执行像read(offset)这样的操作并将其转换为正确块中的偏移量。

希望有所帮助。