内存映射文件

利用虚拟内存技术将文件I/O作为普通内存访问的方法叫做文件的内存映射

文件的内存映射可以将一个磁盘块映射成内存的一页(或多页)。开始的文件访问是按照普通请求页面调度来进行的,这样的话就会产生页错误,因为页上没有相应的内容,这样的话,一页大小的部分文件从文件系统读入物理页(有的系统会一次读入多个一页大小的内容)。这样之后的文件的读写就会按照通常的内存访问来处理,这样的话就简化了文件访问和使用,因为我们现在是面向内存操作,而不是通过系统调用去read和write去每次访问都去进行磁盘访问了

有的操作系统只能通过特定的系统调用才可以提供内存映射,而如果是通过标准的系统调用处理所有其他文件I/O,然而有的系统不管文件是否说明为内存映射,都选择对文件进行内存映射

就拿Solaris为例来说明,如果一个文件说明为内存映射(采用系统调用mmap()),那么Solaris将该文件映射到进程的地址空间中,如果一个文件采用普通系统调用比如说open()、read()、write()来用于打开和访问,那么Solaris仍然对文件进行内存映射,不过是将其映射到的是内核地址空间,无论文件是如何打开的,Solaris都会将所有文件I/O作为内存映射,这样可以允许文件访问在高效的内存子系统当中运行

多个进行可以允许将同一个文件映射到各自的虚拟内存中,这样就可以进行数据共享了,其中任一进程修改虚拟内存中的数据,都会为其他映射相同文件部分的进程所见。每个共享进程的虚拟内存表都指向物理内存的同一页,该页有磁盘块的复制,这种内存共享如下所示

内存映射文件

内存映射的系统调用还支持写时复制功能,允许进程共享只读模式的文件,但也有它们所修改数据的各自的副本

UNIX和Linux系统使用mmap()系统调用进行内存映射,而使用POSIX兼容的shmget()与shmat()系统调用进行内存共享,也就是说内存映射和内存共享的机制是不同的

而对于Windows NT、Windows 2000和Windows XP系统,共享内存是通过内存映射文件来实现的,这些系统可以通过共享内存来通信,而共享内存是通过映射同样文件到其虚拟地址空间来实现的,内存映射文件作为相互通信进程的共享内存区域,它允许我们在WIN32进程中保留一段内存区域,把硬盘或页文件上的目标文件映射到这段虚拟内存中

内存映射文件