mmap
读写文件,一般有两种方式。
一种是open一个文件,然后使用read系统调用读取文件的一部分或全部。这个read过程是这样的:内核将文件中的数据从磁盘区域读取到内核页高速缓冲区,再从内核的高速缓冲区读取到用户进程的地址空间。这里就涉及到了数据的两次拷贝:磁盘->内核,内核->用户态。
而且当存在多个进程同时读取同一个文件时,每一个进程中的地址空间都会保存一份副本,这样肯定不是最优方式的,造成了物理内存的浪费。看下图:
共享存储映射mmap
open一个文件,然后调用mmap系统调用,将文件的内容的全部或一部分直接映射到进程的地址空间,映射完成后,进程可以像访问普通内存一样做其他的操作,比如memcpy等等。mmap并不分配物理地址空间,它只是占有进程的虚拟地址空间。这跟第一种方式不一样的,第一种方式需要预先分配好物理内存,内核才能将页高速缓冲中的文件数据拷贝到用户进程指定的内存空间中。
进程A和进程B都将该页映射到自己的地址空间, 当进程A第一次访问该页中的数据时, 它生成一个缺页中断。内核将文件的这一页数据读入到内核高速缓冲区中,并更新进程的页表,使页表指向内核缓冲中的这一页。以后, 当进程B访问同一页面而出现缺页中断时, 该页已经在内存, 内核只需要将进程B的页表登记项指向次页即可. 如下图所示:
1,将文件的内容的全部或一部分直接映射到进程的地址空间,而不是预先分配物理内存。
2,第一次访问该页中的数据时, 它生成一个缺页中断。内核将文件的这一页数据读入到内核高速缓冲区(page cache)中,并更新进程的页表,使页表指向内核缓冲中的这一页。page cache就是内核的缓存区。
3,因为文件和进程地址具有映射关系,所以只要一个内核态的缓存(page cache),没有用户态的缓冲区(user buffer),所以通过mmap读的时候可以直接从内核态的缓存读(page cache),不用从page cache拷贝到user buffer的过程。