c++ - mmap问题,分配大量内存

标签 c++ c memory mmap

我有一些需要解析的大文件,人们一直在推荐 mmap,因为这样可以避免将整个文件分配到内存中。

但是看着“顶部”,它看起来确实像我将整个文件打开到内存中,所以我想我一定是做错了什么。 '顶级节目 >2.1 gig'

这是一个显示我在做什么的代码片段。

谢谢

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <sysexits.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <cstring>
int main (int argc, char *argv[] ) {
  struct stat sb;
  char *p,*q;
  //open filedescriptor
  int fd = open (argv[1], O_RDONLY);
  //initialize a stat for getting the filesize
  if (fstat (fd, &sb) == -1) {
    perror ("fstat");
    return 1;
  }
  //do the actual mmap, and keep pointer to the first element
  p =(char *) mmap (0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
  q=p;
  //something went wrong
  if (p == MAP_FAILED) {
    perror ("mmap");
    return 1;
  }
  //lets just count the number of lines
  size_t numlines=0;
  while(*p++!='\0')
    if(*p=='\n')
      numlines++;
  fprintf(stderr,"numlines:%lu\n",numlines);
  //unmap it
  if (munmap (q, sb.st_size) == -1) {
    perror ("munmap");
    return 1;
  }
  if (close (fd) == -1) {
    perror ("close");
    return 1;
  }
  return 0;
}

最佳答案

不,您正在做的是将文件映射到内存中。这与实际将文件读入内存不同。

如果您要读入它,则必须将整个内容传输到内存中。通过映射它,您可以让操作系统处理它。如果您尝试读取或写入该内存区域中的某个位置,操作系统将首先为您加载相关部分。除非需要整个文件,否则它不会加载整个文件。

这就是您获得性能提升的地方。如果你映射整个文件但只更改一个字节然后取消映射,你会发现根本没有多少磁盘 I/O。

当然,如果您触摸文件中的每个字节,那么是的,它会在某个时间点全部加载,但不一定一次全部加载到物理 RAM 中。但即使您预先加载整个文件也是如此。如果没有足够的物理内存来容纳所有数据,操作系统将换出部分数据,以及系统中其他进程的数据。

内存映射的主要优点是:

  • 您推迟阅读文件部分,直到需要它们(并且,如果它们从不需要,它们就不会被加载)。因此,在加载整个文件时没有大笔的前期成本。它摊销了装载成本。
  • 写入是自动化的,您不必写出每个字节。只需关闭它,操作系统就会写出更改的部分。我认为当内存被换出时也会发生这种情况(在物理内存不足的情况下),因为您的缓冲区只是文件的一个窗口。

请记住,您的地址空间使用量和物理内存使用量之间很可能存在脱节。您可以在只有 1G RAM 的 32 位机器中分配 4G 的地址空间(理想情况下,尽管可能存在操作系统、BIOS 或硬件限制)。操作系统处理与磁盘之间的分页。

并回答您的进一步澄清请求:

Just to clarify. So If I need the entire file, mmap will actually load the entire file?

是的,但它可能不会同时在物理内存中。操作系统会将位换回文件系统以引入新位。

但如果您手动读取了整个文件,它也会这样做。这两种情况的区别如下。

通过手动将文件读入内存,操作系统会将您的部分地址空间(可能包含数据,也可能不包含)交换到交换文件中。完成后,您将需要手动重写文件。

通过内存映射,您有效地告诉它使用原始文件作为额外的交换区域仅用于该文件/内存。而且,当数据写入那个交换区时,它会立即影响实际文件。因此,完成后无需手动重写任何内容,也不会影响正常的交换(通常)。

它实际上只是文件的一个窗口:

memory mapped file image

关于c++ - mmap问题,分配大量内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1972765/

相关文章:

c++ - 没有运算符 ">> "匹配这些操作数

c++ - 程序因二进制错误而停止

c++ - 星号之前还是之后?

c++ - 从 C/C++ 代码中删除注释

ios - ARCGIS iOS - map 图层内存问题

c++ - 单例实例释放

c++ - 我将如何使用此优先级队列弹出和推送?

类似于R的C概率库

c - 在 linux 内核中持有互斥量时 sleep

堆外的android内存管理