除了页面级映射之外,文件的mmap可以用其他任何方式完成吗?

时间:2017-02-15 08:36:05

标签: c memory-management mmap

最近在一次采访中,我被问到mmap是否可以直接以二进制模式映射程序;没有页面参考。

我认为这是不可能的,因为它

  

允许应用程序将文件映射到内存中,这意味着存在   存储器地址与存储器中的字之间的一对一对应关系   文件。程序员然后可以直接通过内存访问文件,   与任何其他内存驻留数据相同 - 它是偶数   可以允许写入内存区域以透明映射   回到磁盘上的文件

访问没有涉及分页的文件听起来不对。

我仍然想知道mmap是否可以通过页面方式以任何其他方式将文件映射到内存中。

=====
the page way
=====
  

页面是可以具有不同内存的最小内存单位   权限和行为。因此,页面是构建块   内存映射,而后者又是内存的构建块   进程地址空间。 mmap()系统调用在页面上运行。都   addr和offsetparameters必须在页面大小上对齐   边界。也就是说,它们必须是页面大小的整数倍。

     

因此,映射是页面的整数倍。如果   调用者提供的len参数未在页面上对齐   边界 - 可能是因为底层文件的大小不是倍数   页面大小 - 映射向上舍入到下一个整页

2 个答案:

答案 0 :(得分:1)

如果我们使用维基百科page的定义:

,所有内存映射都涉及页面级映射
  

页面,内存页面或虚拟页面是固定长度的连续虚拟内存块,由页表中的单个条目描述。它是虚拟内存操作系统中内存管理的最小数据单元。

man 2 mmap手册页中所述,

  

mmap()在调用进程的虚拟地址空间中创建一个新映射。

映射由页表中的条目定义。

因此,基本上,mmap()是一种在页面级别管理虚拟内存的工具。

面试官可能试图找出你是否理解低级I / O(read()write())和文件支持的内存映射行为之间的区别。

如果使用O_DIRECT标志打开文件,内核会尝试将数据直接传输到用户空间缓冲区,绕过页面缓存。

由于内存映射的工作方式,使用带有open()标志或不带O_DIRECT标志的后备文件MAP_SHARED对内存映射没有影响。

MAP_PRIVATE / PROT_NONE标志是否影响映射的访问部分使用的内存是否保留在页面缓存中。通常,Linux内核使用写时复制方法:页面在页面缓存中保持只读,直到第一次写入访问。此时,私有映射被复制到新页面(或被逐出),共享映射标记为read-写。它有点复杂,但效率很高。但是,所有这些都依赖于虚拟内存分页。)

甚至可以构建一个完全没有后备的内存映射(SIGBUS映射)。对映射的任何访问都会导致内核生成O_DIRECT信号(尝试访问的线程),该信号可以被进程捕获。信号处理程序可以解码并跳过指令,从而模拟存储器访问。它甚至可以使用Map<String, Student> students = new HashMap<String, Student>(); Student maryIn = new Student(); maryIn.setName("Mary"); students.put(maryIn.getName(), maryIn); Student maryOut = students.get("Mary"); 从文件中读取一个或多个字节。同样,映射基于虚拟内存,因此是页面;没有用于映射的RAM,而是模拟了所有访问。这很少使用,因为它难以想象地慢。

答案 1 :(得分:0)

分页(至少在现代操作系统和体系结构上) 机制通过物理内存进行管理。

我建议您read more关于此主题,但基本上使用虚拟物理地址寻址) >地址。

物理虚拟地址之间的映射通常使用MMU在硬件中完成,并使用 pages 进行组织。使用此概念,内存页面定义了一系列物理和虚拟地址之间的映射。

操作系统还在低级页面管理上方添加了几个层,mmap是分页系统的用户界面,允许您操作页面。 特别是,它允许您将内存页面(请记住,一系列虚拟地址)映射到物理内存以外的其他内容,例如存储在硬盘驱动器上的文件。

总之,你可以使用内存的唯一方式是通过这个分页系统,所以为了回答你的问题,访问某些东西没有任何意义(作为文件,物理内存或其他任何东西) )“除了页面方式以外的任何其他方式”。