CSAPP 读书笔记-第九章虚拟内存
9.1 物理和虚拟寻址
早期的 PC 使用物理寻址,而且诸如数字信号处理器、嵌入式微控制器以及 Cray 超级计算机这样的系统仍然使用这种寻址方式。然而,现代处理器使用的是一种称为虚拟寻址(virtual addressing)的寻址形式。
使用虚拟寻址,CPU 通过生成一个虚拟地址(Virtual Address,VA)来访问主存,这个虚拟地址在被送到内存之前先转换成适当的物理寻址。将一个虚拟地址转换为物理地址的任务叫做地址翻译(address translation)。就像异常处理一样,地址翻译需要 CPU 硬件和操作系统之间的紧密合作。CPU 芯片上叫做内存管理单元(Memory Management Unit,MMU)的专用硬件,利用存放在主存中的查询表来动态翻译虚拟地址,该表的内容有操作系统管理。
9.3 虚拟内存作为缓存的工具
概念上而言,虚拟内存被组织为一个由存放在磁盘上的 N 个连续的字节大小的单元组成的数组。磁盘上数组的内容被缓存在主存中。磁盘(较低层)上的数据被分割成块,这些块作为磁盘和主存(较高层)之间的传输单元。VM 系统通过将虚拟内存分割为称为虚拟页(Virtual Page,VP)的大小固定的块来处理这个问题。每个虚拟页的大小为 P 字节。物理内存被分割为物理页(Physical Page,PP),大小也为 P 字节(物理页也被称为页帧(page frame))。
在任意时刻,虚拟页面的集合都分为三个不相交的子集:
- 未分配的:不占用任何磁盘空间
- 缓存的:已缓存在物理内存中的已分配页
- 未缓存的:未缓存在物理内存中的已分配页
9.3.1 DRAM 缓存的组织结构
DRAM 缓存中的不命中比起 SRAM 缓存中的不命中要昂贵得多,这是因为 DRAM 缓存不命中要由磁盘来服务。
因为大的不命中处罚和访问第一个字节的开销,虚拟页往往很大,通常是 4KB~2MB。
因为对磁盘的访问时间很长,DRAM 缓存总是使用写回,而不是直写。
9.3.2 页表
页表存放在物理内存中,将虚拟页映射到物理页。
9.3.4 缺页
在虚拟内存的习惯说法中,DRAM 缓存不命中称为缺页(page fault)。
9.3.6 又是局部性救了我们
如果工作集的大小超出了物理内存的大小,那么程序将产生一种不幸的状态,叫做抖动(thrashing),这时页面将不断地换进换出。
9.8 内存映射
Linux 通过将一个虚拟内存区域与一个磁盘上的对象(object)关联起来,以初始化这个虚拟内存区域的内容,这个过程称为内存映射(memory mapping)。
9.8.1 再看共享对象
每个 C 程序都需要来自标准 C 库的诸如 printf
这样的函数。那么,如果每个进程都在物理内存中保持这些常用代码的副本,那就是极端的浪费了。内存映射给我们提供了一种清晰的机制,用来控制多个进程如何共享对象。
如果一个进程将一个共享对象映射到它的虚拟地址空间的一个区域内,那么这个进程对这个区域的任何写操作,对于那些也把这个共享对象映射到它们虚拟内存的其他进程而言,也是可见的。而且,这些变化也会反映在磁盘上的原始对象中。