进程地址空间
每个进程都有自己的地址空间。对32位进程来说,由于32位指针可以表示从0x00000000到0xFFFFFFFF之间的任一值,地址空间的大小为4GB。对64位进程来说,由于64位指针可以表示从0x00000000'00000000到0xFFFFFFFF'FFFFFFFF之间的任一值, 地址空间大小为16GB。
其实这个地址空间是不存在的,也就是我们所说的进程虚拟内存空间。
linux操作系统每个进程的地址空间都是独立的,其实这里的独立说得是物理空间上得独立。那相同的虚拟地址,不同的物理地址,他们之间是怎样联系起来的呢?当一个程序被执行时,该程序的内容必须被放到进程的虚拟地址空间,对于可执行程序的共享库也是如此。可执行程序并非真正读到物理内存中,而只是链接到进程的虚拟内存中。
在进程创建的过程中,程序内容被映射到进程的虚拟内存空间,为了让一个很大的程序在有限的物理内存空间运行,我们可以把这个程序的开始部分先加载到物理内存空间运行,因为操作系统处理的是进程的虚拟地址,如果在进行虚拟到物理地址的转换工程中,发现物理地址不存在时,这个时候就会发生缺页异常(nopage),接着操作系统就会把磁盘上还没有加载到内存中的数据加载到物理内存中,对应的进程页表进行更新。也许你会问,如果此时物理内存满了,操作系统将如何处理?
当物理内存溢出时,linux使用"最近最少使用(LeastRecently Used ,LRU)"(很多缓存技术都是这个原则)页面调度技巧来公平地选择哪个页可以从系统中删除。
内存映射文件
内存映射文件是由一个文件到进程地址空间的映射,而不是真正意义上的映射内存。通过文件映射这种使磁盘文件的全部或部分内容与进程地址空间的某个区域建立映射关联的能力,可以直接对被映射的文件进行访问,而不必执行文件I/O操作也无需对文件内容进行缓冲处理。。内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。
使用内存映射文件的一般流程
如果有十几GB乃至几十GB容量的巨型文件,显然不能一次将文件映像全部映射进来。对于这种情况只能依次将大文件的各个部分映射到进程中的一个较小的地址空间。这需要对上面的一般流程进行适当的更改:
1)映射文件开头的映像。
2)对该映像进行访问。
3)取消此映像
4)映射一个从文件中的一个更深的位移开始的新映像。
5)重复步骤2,直到访问完全部的文件数据。