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

标签 c memory-management mmap

最近在一次面试中,有人问我mmap是否可以直接以二进制模式对程序进行映射;没有页面引用。

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

allows an application to map a file into memory, meaning that there is a one-to-one correspondence between a memory address and a word in the file. The programmer can then access the file directly through memory, identically to any other chunk of memory-resident data—it is even possible to allow writes to the memory region to transparently map back to the file on disk

在不涉及分页的情况下访问文件听起来是错误的。

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

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

The page is the smallest unit of memory that can have distinct permissions and behavior. Consequently, the page is the building block of memory mappings, which in turn are the building blocks of the process address space. The mmap( ) system call operates on pages. Both the addr and offsetparameters must be aligned on a page-sized boundary. That is, they must be integer multiples of the page size.

Mappings are, therefore, integer multiples of pages. If the len parameter provided by the caller is not aligned on a page boundary—perhaps because the underlying file's size is not a multiple of the page size—the mapping is rounded up to the next full page

最佳答案

如果我们使用维基百科的page定义,所有内存映射都涉及页面级映射。 :

A page, memory page, or virtual page is a fixed-length contiguous block of virtual memory, described by a single entry in the page table. It is the smallest unit of data for memory management in a virtual memory operating system.

man 2 mmap 中所述手册页,

mmap() creates a new mapping in the virtual address space of the calling process.

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

因此,本质上,mmap() 是一个用于管理页面级别虚拟内存的工具。

<小时/>

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

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

由于内存映射的工作方式,使用或不使用 O_DIRECT 标志对后备文件进行 open() 编辑不会对内存映射产生影响。

(无论用于映射的访问部分的内存是否保留在页面缓存中,MAP_SHARED/MAP_PRIVATE 标志都会产生影响不是。通常,Linux 内核使用写时复制方法:页面在页面缓存中保持只读状态,直到第一次写访问。此时,私有(private)映射会被复制到新页面(或被逐出),并且共享映射被标记为可读写。它有点复杂,但效率很高。不过,这一切也都依赖于虚拟内存分页。)

甚至可以构造一个完全没有支持的内存映射(PROT_NONE 映射)。对映射的任何访问都会导致内核生成一个 SIGBUS 信号(发送给尝试访问的线程),该信号可以被进程捕获。信号处理程序可以解码并跳过指令,从而模拟内存访问。它甚至可以使用O_DIRECT从文件中读取一个或多个字节。同样,映射基于虚拟内存,因此也基于页;只是没有 RAM 用于映射,而是模拟所有访问。这很少使用,因为它慢得难以想象。

关于c - 除了页面级映射之外,文件的 mmap 可以通过任何其他方式完成吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42244294/

相关文章:

JavaScript,没有引用的对象实例

c - NFS 中的强制属性刷新

c++ - 将数字从范围转换为另一个范围的更快方法

c++ - 使用 Arduino 上的 atoi 和 itoa 从 int 转换为字节数组然后返回 int 进行传输

c++ - 堆损坏 : What could the cause be?

c# - 监视 Windows 服务中的内存

python - 从 mmap 迭代并用 C 中的 block 读取的输入文件的 2 个不同输出

c - 如何创建用于mmap文件操作的filep(Linux内核驱动)?

android - openSL ES Android : Irregular audio callback(s)

c - 来自 munmap 的 Linux 错误