What every programmer should know about memory, Part 3: Virtual Memory

原文:What every programmer should know about memory, Part 3: Virtual Memory

4 Virtual Memory

虚拟内存(virtual memory)是处理器的一个子系统,它给每个进程提供虚拟地址空间(virtual address space)。这让每个进程以为自己在系统中是独自一人。

wiki词条

虚拟内存的作用在于为进程提供“看上去”连续的地址空间,这么做的好处在于程序不需要处理内存碎片的问题了。

虚拟地址空间由CPU的Memory Management Unit(MMU)实现,操作系统必须填写页表数据结构(page table data structures,见wiki词条),大多数CPU自己完成余下的工作。

把虚拟地址(virtual address)作为输入交给MMU做翻译。在32位系统中虚拟地址是32位的,在64位系统中是64位的。

4.1 Simplest Address Translation

MMU可以逐页(page)的将虚拟地址翻译成物理地址的,和cache line一样,虚拟地址被分割成多个部分,这些部分则被索引到不同的表(table)里,这些表用来构造最终的物理地址。最简单的模型则只拥有一个级别的表(only one level of tables)。

Figure 4.1: 1-Level Address Translation

虚拟地址的结构:

页目录的存储:

先弄个速算表,下面会用得着:

拿x86系统,4MB页举例:

4.2 Multi-Level Page Tables

多级页表(page table),注意原文写到这里用页表(page table)而不是页目录(page directory),这两个实际上是一个东西。

上面的例子拿4MB页来举例的,不过4MB页表不常见,这是因为操作系统执行的很多操作是按照页来对齐的,意思是每个页的基地址之间都差4MB的倍数,就算你要用1k内存也要申请了一个4MB的页,这造成了大量的浪费。

真实世界里32位机器大多用4kB页,同样多见于64位机器。

为啥4kB页,单级页表不行:

解决办法是使用多级页表。它们能够代表一个稀疏的巨大的页表,可以做到对没有被使用的区域(原文没有讲区域是啥)不需要分配内存。这种形式跟为紧凑,可以为许多进程提供页表,同时又不对性能产生太大影响。

Figure 4.2: 4-Level Address Translation

上面是一个4级页表:

得到物理地址的步骤,Page tree walking:

Page table tree尺寸对性能的影响:

Page table tree布局:

个人总结,前面讲的对于多少连续的寻址空间,各级别页表需要多少个是这么计算的:

下面举连续的2MB寻址空间(页大小为4kB):

下面举例连续的1GB寻址空间(页大小为4kB):

同理如果是连续的2GB寻址空间(页大小为4kB):

4.3 Optimizing Page Table Access

TLB:

4.3.1 Caveats Of Using A TLB

讲了几种优化TLB cache flush的手段,不过没有讲现代CPU使用的是哪一种。

个人认为这段不用太仔细读,只需要知道存在一种手段可以最少范围的flush TLB cache entry就行了。

4.3.2 Influencing TLB Performance

使用大页:

提高虚拟页最小尺寸(前面讲的大页是可选的)也会产生问题:

$ eu-readelf -l /bin/ls
Program Headers:
  Type   Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
...
  LOAD   0x000000 0x0000000000400000 0x0000000000400000 0x0132ac 0x0132ac R E 0x200000
  LOAD   0x0132b0 0x00000000006132b0 0x00000000006132b0 0x001a71 0x001a71 RW  0x200000
...

Figure 4.3: ELF Program Header Indicating Alignment Requirements

这是一个x86-64可执行二进制的头,里面规定了内存对齐单位是0x200000 = 2,097,152 = 2MB,如果页尺寸比这个大就不行了。

另一个使用大页的影响是减少page table tree的层级,因为offset变大了,那么剩下的留给页表的部分就变少了,那么page tree walking就更快了,那么TLB missing所要产生的工作就变少了。

下面这段没有看懂:

Beyond using large page sizes, it is possible to reduce the number of TLB entries needed by moving data which is used at the same time to fewer pages. This is similar to some optimizations for cache use we talked about above. Only now the alignment required is large. Given that the number of TLB entries is quite small this can be an important optimization.

4.4 Impact Of Virtualization

大致意思是现代虚拟化技术能够消解大部分因虚拟化导致的TLB性能损失,但是这个开销不会完全消失。