mmap()
将一个已经打开的文件的内容映射的它的用户空间。
1.解释
“文件的内容映射的它的用户空间”是什么意思?
我们知道linux内核中,物理内存在内存中以页面大小为单位进行维护,而页式内存管理简单的说是给定一个虚拟地址0xA,经过页式映射,能够找到物理内存所对应的页面地址,数据真正存放的位置。
Linux内存管理以页面为单位,对用户空间的管理当然也是以页面为单位,而每个虚存地址都会对应着某个具体页面。
那么上面的那句话就是说在用户空间建立好虚拟地址到页面的映射,将文件的内容读到内存中指定的页面,这样程序可以通过虚拟地址再经过页式映射,就能找到文件在页面中的内容。
那么同样是将文件内容读到内存中,它和普通的文件读取read()有什么不同呢?
a.读取方式不同,mmap()读取文件内容的方式是通过缺页中断,当发现虚拟地址对应的页式映射尚未建立,就会通过缺页中断将文件内容读取到虚存地址所映射的页面中。
而普通的文件读取就是通过read()读取文件内容。
b.访问方式不同,mmap()后,访问文件内容就像访存一样简单。
2.主要步骤
mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset)
1.找到一块大小为length的未被映射的虚存空间
2.为找到的虚存空间分配vm_area_struct结构,用来映射后来读到内存页面中的文件内容
3.设置vm_area_struct的各个成员信息,比如将vm_area_struct中的vm_pgoff设置为offset,这样当发生缺页异常时,就会从文件偏移vm_pgoff的地方开始读取文件内容到指定页面。
4.将此vm_area_struct结构插入本进行的vm_area_struct队列中
5.结束
这就结束了?并没有看到具体文件读到内存中的操作啊?甚至连vm_area_struct所对应页面映射都没有建立,页面都没有分配。
其实这里的mmap()仅仅是建立其虚存结构vm_area_struct。而把真正的页面映射推迟到确实需要读取文件内容时,以缺页异常的方式读取。这样做的好处一方面避免不必要的文件读取,因为程序可能建立完映射并不访问文件内容;另一方面,节省不必要的内存页面开销。否则可能会导致频繁的页面换入换出。