最近,在一次采访中,有人问我,mmap是否可以直接在二进制模式下进行程序映射,而不需要页面引用。
我认为这是不可能的,因为
允许应用程序将文件映射到内存中,这意味着内存地址和文件中的单词之间存在一对一的对应关系。然后,程序员可以通过内存直接访问文件,与任何其他内存块相同--驻留数据--甚至允许写入内存区域透明地映射回磁盘上的文件。
在不涉及分页的情况下访问文件听起来是错误的。
不过,我还是想知道mmap是否有任何方法可以在内存中以除页面方式之外的任何方式映射文件。
=====
the page way
=====页面是最小的内存单元,可以具有不同的权限和行为。因此,页面是内存映射的构建块,而内存映射又是进程地址空间的构建块。重要的mmap()系统调用在页面上运行。必须在页面大小的边界上对齐相应的addr参数和非匹配参数.也就是说,它们必须是页面大小的整数倍数。 因此,映射是页面的整数倍数。如果调用方提供的辅助len参数在页面边界上没有对齐--可能是因为底层文件的大小不是页面大小的倍数--则映射被舍入到下一个完整页面
发布于 2017-02-15 10:26:40
如果我们使用维基百科对页面的定义,所有内存映射都涉及页级映射。
页、内存页或虚拟页是虚拟内存的固定长度连续块,由页表中的单个条目描述。它是虚拟内存操作系统中内存管理的最小数据单元。
如man 2 mmap手册页所述,
mmap()在调用进程的虚拟地址空间中创建一个新的映射。
映射是由页面表中的条目定义的。
因此,从本质上说,mmap()是一个管理页面级虚拟内存的工具。
面试官可能想弄清楚你是否理解低水平I/O (read(),write())和文件支持的内存映射行为之间的区别。
如果使用O_DIRECT标志打开文件,内核将尝试将数据直接传输到用户空间缓冲区,从而绕过页面缓存。
由于内存映射的工作方式,无论是否使用O_DIRECT标志编辑备份文件O_DIRECT都不会对内存映射产生影响。
( MAP_SHARED/MAP_PRIVATE标志对用于映射访问部分的内存是否停留在页面缓存中有影响。通常,Linux内核使用的是一种写上复制的方法:页面在第一次写访问之前都是只读的。此时,私有映射被复制到新页面(或被逐出),共享映射被标记为读-写。这有点复杂,但很有效率。但是,所有这些都依赖于虚拟内存分页。)
甚至可以在没有支持的情况下构造内存映射( PROT_NONE映射)。对映射的任何访问都会导致内核生成一个SIGBUS信号(指向试图访问的线程),进程可以捕获该信号。信号处理程序可以解码和跳过指令,从而模拟内存访问。它甚至可以使用O_DIRECT从文件中读取一个或多个字节。同样,映射是基于虚拟内存的,因此页面;没有用于映射的RAM,而是对所有访问进行仿真。这是很少使用,因为它是难以想象的缓慢。
发布于 2017-02-15 10:26:28
分页是(至少在现代OSes和体系结构上),通过物理内存管理机制。
我建议您在这个主题上使用阅读更多,但基本上物理内存(使用物理地址)是通过虚拟地址从内核和用户空间访问的。
物理地址和虚拟地址之间的映射通常使用MMU在硬件中完成,并且使用页面进行组织。使用此概念,内存页定义了物理地址和虚拟地址之间的映射。
操作系统还在低级页面管理之上添加了几个层,mmap是分页系统的用户界面,允许您操作页面。特别是,它允许您将内存页(记住,一系列虚拟地址)映射到物理内存以外的其他内容,例如存储在硬盘驱动器上的文件。
总之,您可以使用内存的专用方式是通过这个分页系统进行的,因此要回答您的问题,“以页面方式以外的任何其他方式”访问某物(作为文件、物理内存或其他任何东西)是没有任何意义的。
https://stackoverflow.com/questions/42244294
复制相似问题