笔者:YY同学
CPU 处理过程
- 获取指令
- 解码指令
- 执行指令
- 获取下一个指令
虚拟内存(VM)
物理地址(Physical Address)是真实的地址,连续不可分割。但是为了方便使用,需要设计一种非连续性地址,即虚拟地址(Virtual Address)。虚拟地址好比就是物理地址的一个别名,两种地址一一对应,其转换和翻译依赖内存管理单元(MMU)进行。这些虚拟地址统称为虚拟内存。
内存转译步骤:
- 程序存储于一个真实的物理地址,但是返回一个虚拟地址标签
- CPU 获取虚拟地址的进入位置,并访问 MMU 进行转译
- MMU 将真实的物理地址信息返回 CPU,CPU 完成数据访问
虚拟内存优点:
- 虚拟地址在形式上是连续的,能帮助 CPU 更快地寻址
- 新分配的进程内存无需连续
- 保护真实物理地址,理论上更加安全
虚拟内存的其他特征:
- VM 只是 Lookup Table 的一种实现方式,Lookup Table 则是一种被安置于 CPU 的硬件层面的技术。
- 每个独立进程拥有自己的 Page Table,而 VM 的任务是负责教会 CPU 如何理解 Page Table。
- 父子进程会共享同一个虚拟内存。
- 通常会保留一个 Virtual Page,这个 page 不会被使用,所以总的 memory 大小为 2 32 − 1 2^{32}-1 232−1。
- 虚拟地址与物理地址对应关系并不是永久的,当 Lookup Table 放满时,一些旧的物理地址可能会被新的地址替换。
查找表(Lookup Table)
MMU 内部存在多个 Lookup Table,存储物理地址与对应的虚拟地址。OS kernel 负责将这些 table 不停地经过上下文转换(context switching)放到 MMU 中处理。
分页技术(Paging)
在此之前,我们需要知道两件事情:
- 一台机器总的物理内存大小是固定的,总的存储量是一定的。
- Lookup Table 仅仅是表示虚拟地址与物理地址之间的一个关系,Table 存储的总容量和存储地址对应关系的多少并不会影响物理地址的大小。
上面我们已经计算过原始 Lookup Table 的大小为 16G,为了更好地节约 Lookup Table 的大小,我们引入分页技术的概念:
分页是指将总的内存(用虚拟内存更方便理解,因为它连续)按照固定的大小分成块,这样的块叫做页(Page)。就像平时我们用 Word 进行文章排版的时候一样,每页纸上(Frame)会有差不多数量的文字,然后给每页标上页码。如果每页放入的字数变多则页码数量会减少,反之页码会增加。同样地,如果将虚拟内存按照上述方法分页,然后将页码表示为内存的地址,那么只要一页可以放下更多数据那么内存地址数量就可以大大减少,从而 Lookup Table 的大小也会减少,岂不美哉?
例如如果按照每页大小 12 bits,那么只需要 20 bits =
2
20
2^{20}
220 页,相比于原先的
2
32
2^{32}
232 页,数量已经是大大减少。
PS:图中紫色部分为 page;橙色部分为单个 page 里的偏移位置,相当于一页里第几行的概念;单个紫色块的大小叫 page size,记得求大小的时候需要乘地址长度。
注意:
- 储在 MMU 内部的 Lookup Table 又称为 Page Table,并且 page 和 offset 的位数可以根据需要自己拟定,只要保证 page bit + offset bit = 32 bits 即可。
- 物理内存实际上并没有被分页,只是“看上去”被分页了,因为从虚拟内存的角度更方便理解。
- 分页的页数一定是整数,N’ = ceil(N)。好比打印的时候最后一张纸上只打了几个字,但这也算单独的一页。
- 注意 Page 和 Frame 的区别:Page 是属于虚拟内存的概念,实际上并不存在,只是为了方便人们理解被创造出来了;Frame 是属于物理内存的概念,是真实存在的,真实物理内存按照固定大小分成的页叫做 frame,所以可以说 Page 是 Frame 的别名。
- 区别 Page Table 和 Lookup Table:道理同上,Page Table 是虚拟内存的概念,是假想的;Lookup Table 是物理内存的概念,是真实存在的物理地址与虚拟地址对照表。
- 分页技术并不是完美的,可能存在内部片段空间浪费的问题(Internal Fragmentation),这一部分资源无法被利用。MMU 还需要设置单位内存上限,并且实时监控这部分内存的情况,防止内存溢出。
两道经典例题
页替换(Page Replacement)
CPU 根据虚拟地址在 Page Table 中寻找对应的物理地址,如果有则完成转译。但是如果没有对应的关系,CPU 则需要访问 Memory 获取物理地址并记录到 Page Table 中以便下次使用,还需要向 OS 反馈总的页面缺失数量(Page Fault)。但是 Page Table 大小有限,总有所有空间都放满地址的情况,此时需要根据不同算法删除 page 里的部分旧物理地址,再将新的地址信息写入,这个过程叫做页替换。
三种替换算法
以 4 frames 为样例,0~7 代表 3 bits 的 virtual page 的十进制编号。
- 先进先出算法(FIFO):当 Page Table 满的时候,替换最早写入的 frame。
Access Page No. | 0 | 1 | 4 | 2 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | 3 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Frame1(Latest) | 0 | 1 | 4 | 2 | 3 | 3 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | 1 |
Frame2 | 0 | 1 | 4 | 2 | 2 | 3 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 7 | |
Frame3 | 0 | 1 | 4 | 4 | 2 | 3 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 4 | ||
Frame4(Oldest) | 0 | 1 | 1 | 4 | 2 | 3 | 6 | 5 | 1 | 0 | 2 | 3 | 3 | |||
Page Fault | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
Page Fault: 14
特点: 单纯的顺序替换,page 的写入顺序基本上不变。
- 最常用算法(LRU):当 Page Table 满的时候,替换最不常用的 frame。
Access Page No. | 0 | 1 | 4 | 2 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | 3 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Frame1(Most Recent) | 0 | 1 | 4 | 2 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | 3 |
Frame2 | 0 | 1 | 4 | 2 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | |
Frame3 | 0 | 1 | 4 | 4 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | ||
Frame4(Least Recent) | 0 | 1 | 1 | 4 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | |||
Page Fault | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
Page Fault: 14
特点: 当一个新的 page 写入之后,不管它是新的或是已经存在于 table 中,它的使用情况都会被刷新成“最新使用”。
- 未来透视算法(Optimal):是一种理想情况,可以看到未来所有会出现的情况。当 Page Table 满的时候,替换离未来下一个相同 page 间隔最远的 frame。
特点:
Access Page No. | 0 | 1 | 4 | 2 | 3 | 2 | 6 | 5 | 1 | 0 | 2 | 3 | 4 | 7 | 1 | 3 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Frame1(Nearst) | 0 | 1 | 1 | 2 | 2 | 1 | 1 | 1 | 0 | 2 | 1 | 1 | 1 | 1 | 3 | 5 |
Frame2 | 0 | 0 | 1 | 1 | 0 | 0 | 0 | 2 | 1 | 5 | 3 | 3 | 3 | 5 | 7 | |
Frame3 | 4 | 0 | 0 | 2 | 2 | 2 | 1 | 5 | 0 | 5 | 5 | 5 | 7 | 1 | ||
Frame4(Furthest) | 4 | 3 | 3 | 6 | 5 | 5 | 0 | 2 | 0 | 4 | 7 | 1 | 3 | |||
Page Fault | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 0 |
Page Fault: 10
特点: 对于未来不再出现的 page,其间隔会变成无限大(infinity)。