Gee*_*eek 6 system-programming memory architecture
有人可以用一种易于理解的方式解释类 Unix 系统中内存映射的概念(通过 mmap() 系统调用实现)吗?我们什么时候需要这个功能?
考虑:两个进程可以同时打开同一个文件进行读写,因此两者之间可以进行某种通信。
当进程 A 写入文件时,它首先用一些数据填充它自己的进程特定内存write中的缓冲区,然后调用which 将该缓冲区复制到内核拥有的另一个缓冲区中(实际上,这将是一个页面缓存条目,它内核将标记为脏并最终写回磁盘)。
现在进程 B 从同一个文件中的同一个点读取;read将页缓存中相同位置的数据复制到 B 内存中的缓冲区中。
注意需要两次拷贝:首先将数据从A复制到“共享”内存,然后再从“共享”内存复制到B。
A 可mmap用于直接在其自己的地址空间中使用页面高速缓存。现在它可以将其数据直接格式化到相同的“共享”内存中,而不是填充中间缓冲区,并避免复制。
类似地,B 可以mmap将页面直接放入其地址空间。现在它可以直接访问 A 放入“共享”内存中的任何内容,而无需将其复制到单独的缓冲区中。
(显然,如果您真的想将此方案用于 IPC,则需要某种同步,但这超出了范围)。
现在考虑将 A 替换为存储此文件的任何设备的驱动程序的情况。通过与访问文件mmap,B仍然避免了冗余副本(DMA或任何进入页面缓存是不可避免的,但它并不需要被复制再次到B的缓冲)。
当然也有一些缺点。例如:
如果您的设备和操作系统支持异步文件 I/O,您可以使用它来避免阻塞读/写......但是读取或写入一个 mmapped 页面可能会导致您无法直接处理的阻塞页面错误(尽管您可以尝试避免使用mincore等)
它不会阻止您尝试读取文件的末尾,或以一种很好的方式帮助您附加到它(您需要检查长度或明确truncate文件更大)