Mmap

Binder | 内存拷贝的本质和变迁

芦半山

虚拟地址和数据的关系

所有的数据都存储在物理内存中,而进程访问内存只能通过虚拟地址。因此,若是想成功访问必须得有个前提:

虚拟地址和物理内存之间建立映射关系

若是这层映射关系不建立,则访问会出错。信号11(SIGSEGV)的MAPERR就是专门用来描述这种错误的。

虚拟地址和物理地址间建立映射关系通过mmap完成。这里我们不考虑file-back的mapping,只考虑anonymous mapping。当mmap被调用(flag=MAP_ANONYMOUS)时,实际上会做以下两件事:

  1. 分配一块连续的虚拟地址空间。
  2. 更新这些虚拟地址对应的PTE(Page Table Entry)。

mmap做完这两件事后,就会返回连续虚拟地址空间的起始地址。在mmap调用结束后,其实并不会立即分配物理页。如果此时不分配物理页,那么就会有如下两个问题:

  1. 没有新的物理页分配,那么PTE都更新了哪些内容?
  2. 如果后续使用mmap返回的虚拟地址访问内存,会有什么情况产生呢?

1.1.1 没有新的物理页分配,那么PTE都更新了些什么内容呢?

PTE也即页表的条目,它的内容反映了一个虚拟地址到物理地址之间的映射关系。如果没有新的物理页分配,那这些新的虚拟地址都和哪些物理地址之间建立了映射关系呢?答案是所有的虚拟地址都和同一个zero page(页内容全为0)建立了映射关系。

1.1.2 如果后续使用mmap返回的虚拟地址访问内存,会有什么情况产生呢?

拿到mmap返回的虚拟地址后,并不会有新的物理页分配。此时若是直接读取虚拟地址中的值,则会通过PTE追踪到刚刚建立映射关系的zero page,因此读取出来的值都是0。

如果此时往虚拟地址中写入数据,将会在page fault handler中触发一个正常的copy-on-write机制。需要写多少页,就会新分配多少物理页。所以我们可以看到,真实的物理页是符合lazy(on-demand) allocation原则的。这一点,极大地保证了物理资源的合理分配和使用。

Author

white crow

Posted on

2022-02-16

Updated on

2024-03-25

Licensed under