类 Unix 系统中内存映射的概念

类 Unix 系统中内存映射的概念

有人可以用一种易于理解的方式解释类 Unix 系统中内存映射的概念(通过 mmap() 系统调用实现)吗?我们什么时候需要这个功能?

答案1

考虑:两个进程可以同时打开同一个文件进行读写,因此两者之间可以进行某种通信。

当进程 A 写入文件时,它首先用一些数据填充其自己的进程特定内存内的缓冲区,然后调用write该函数将该缓冲区复制到内核拥有的另一个缓冲区中(实际上,这将是一个页缓存条目,内核将标记为脏并最终写回磁盘)。

现在进程B从同一个文件的同一点读取;read将数据从页缓存中的同一位置复制到 B 内存中的缓冲区中。


请注意,需要两次复制:首先将数据从 A 复制到“共享”内存,然后再次从“共享”内存复制到 B。

A 可以用来mmap使页面高速缓存直接在其自己的地址空间中可用。现在,它可以将其数据直接格式化到相同的“共享”内存中,而不是填充中间缓冲区,并避免复制。

同样,B也可以mmap直接将页面放入它是地址空间。现在,它可以直接访问 A 放入“共享”内存中的任何内容,而无需将其复制到单独的缓冲区中。

(显然,如果您确实想将此方案用于 IPC,则需要某种同步,但这超出了范围)。


现在考虑这样的情况:A 被存储该文件的任何设备的驱动程序替换。通过使用mmap, B访问文件仍然避免冗余副本(DMA 或其他进入页面缓存是不可避免的,但不需要复制再次进入B的缓冲区)。


当然,也有一些缺点。例如:

  • 如果您的设备和操作系统支持异步文件 I/O,您可以使用它来避免阻塞读/写...但是读取或写入映射页面可能会导致您无法直接处理的阻塞页面错误(尽管您可以尝试使用等避免它mincore

  • 它不会阻止您尝试读取文件的末尾,或帮助您以一种很好的方式附加到文件(您需要检查长度或显式truncate增大文件)

相关内容