对整个 4Kb 块使用 mmap() 是否可以,还是一次性对我的整个文件使用 mmap() 更好?

Is it okay to use mmap() for 4Kb blocks all over the place or is it better to mmap() my whole file in one go?

我想处理一个由 4Kb 块组成的文件。

随着事情的发展,我会写更多的数据并映射新的部分,取消映射我不再需要的部分。

当要映射的文件数据总量约为 4Gb 时,仅 4Kb 的 map() 是否太小? (即大约 1,048,576 个单独映射的块)。

我担心进行如此多的小 mmap() 调用最终不会有效率,即使它们很好地定向到我想要使用的确切块。同时,可能还是比我每改一个字节用read()/write()读写这些块

要好

64 位架构上不缺地址space。除非您的代码也必须在 32 位体系结构中工作(现在很少见),否则映射整个文件一次并避免多次 mmap 调用和数千个额外内核对象的开销。随着阅读和写作的变化,这取决于你想要的语义。参见 this answer

在 64 位系统上,您几乎应该一次性映射整个文件或至少整个范围,并让操作系统为您处理分页进出。 mmap 调用本身确实有一些开销。实际上,x86-64 上的用户地址 space 类似于 128 TiB,因此您应该能够毫无问题地映射 1 TiB files/ranges。

据我了解,即使是覆盖多个连续 4kb 页面的单个 mmap() 也需要内核(以及 TLB、MMU...)来处理尽可能多的 virtual/physical关联作为这些页面的数量(这是内存页面的目的;连续的虚拟页面可以映射到非连续的物理页面)。
因此,考虑到这些映射页面的用途,一旦通过唯一或许多 mmap() 调用设置,性能上应该没有任何差异。
但是每次调用 mmap() 可能需要一些开销才能选择要使用的虚拟地址部分 space;单个 mmap() 调用只需选择一次足够大的虚拟位置(如其他答案所述,在 64 位系统上应该不会太困难)但重复调用将多次暗示这种开销。

所以,如果我必须在 64 位系统上处理这种情况,我会一次性 mmap() 整个文件,使用大页面以减少 TLB 的压力。
请注意,一次映射整个文件并不意味着此时使用相同数量的物理内存; virtual/physical 内存关联只会在每个页面第一次被访问时发生。