待补充 811
一、物理和虚拟地址
计算机系统的主内存以M个连续的字节大小的块数组组织而成。其中每个字节都有一个独一无二的物理地址(physical address,PA)。第一个字节的地址为0,下一个字节的地址为1,以此类推。给定了这种组织形式,对于一个CPU来说最自然的寻址方式就是使用物理地址。这种寻址方式被称为物理寻址。图9.1展示了物理寻址的一个例子,在这个例子中展示了从物理地址为4的内存储读取一个字大小数据的加载指令:
当CPU执行加载指令时,它会生成一个有效物理地址并通过内存总线将这个地址传递给主内存。主内存获取从物理地址4开始的4字节大小的字并将其返还到CPU,CPU将这个字存储在寄存器中。
早期的微型计算机使用物理寻址,现在一些嵌入式处理器以及超算也在使用物理寻址。但是,现在的处理器都使用一种虚拟寻址的方式,如图9.2所示:
在虚拟寻址方式下,CPU通过生成一个虚拟地址(virtual address,VA)的方式来访问主内存,虚拟地址随后会在送入内存前转化为物理地址。转化虚拟地址的任务被称为地址翻译。和异常处理一样,地址翻译也需要CPU硬件和操作系统的密切配合。CPU上有称为内存管理模块(memory management unit,MMU)的专用芯片在运行时翻译虚拟地址,使用一个操纵系统管理并存贮在主存中的查找表(look-up table)。
二、地址空间
地址空间是一串有序非负整数地址:
{ 0 , 1 , 2 , . . . } \{0,1,2,...\} {0,1,2,...}
如果地址空间内的整数是连续的,那么这个地址空间就被称为线性地址空间(linear address space)。本文一直假设地址空间是线性地址空间。在一个使用虚拟内存的系统中,CPU从地址空间大小为 N = 2 n N=2^n N=2n大小的虚拟地址空间(virtual address space)中生成虚拟地址:
{ 0 , 1 , 2 , . . . , N − 1 } \{0,1,2,...,N-1\} {0,1,2,...,N−1}
地址空间的大小用2的指数表示,例如一个 N = 2 n N=2^n N=2n的地址空间被称为n位地址空间。 现代操作系统通常支持32位或64位地址空间。
每个系统中同样存在一个物理地址空间,这个物理地址空间对应了系统中的M个字节大小的物理内存:
{ 0 , 1 , 2 , . . . , M − 1 } \{0,1,2,...,M-1\} {0,1,2,...,M−1}
M并不需要一定是2的指数,但为了简化描述我们通常假设 M = 2 m M=2^m M=2m
地址空间的概念是十分重要的,因为它在数据对象(字节)和数据属性(地址)之间做出了明确的区分。当我们意识到了这种区分后,我们就可以进行推广,使得一个数据对象有多个独立的地址,每个地址都从一个不同的地址空间中获取。这就是虚拟内存的基本思想。主内存的每个字节都有一个从虚拟地址空间中选取的虚拟地址,同时还有一个从物理地址空间中选取的物理地址。
练习 9.1
完成下表,填充缺失的表项并且将每个问号都替代位合适的整数。其中单位如下所示:
K
=
2
10
(
K
i
l
o
)
,
M
=
2
20
(
M
e
g
a
)
,
G
=
2
30
(
g
i
g
a
)
,
T
=
2
40
(
T
e
r
a
)
,
P
=
2
50
(
P
e
t
a
)
,
E
=
2
60
(
E
x
a
)
K=2^{10}(Kilo),M=2^{20}(Mega),G=2^{30}(giga),T=2^{40}(Tera),P=2^{50}(Peta),E=2^{60}(Exa)
K=210(Kilo),M=220(Mega),G=230(giga),T=240(Tera),P=250(Peta),E=260(Exa)
答案:
三、虚拟内存作为缓存工具
概念上来讲,虚拟内存以M个连续的字节大小的块组织而成(可以看作数组)。其中每个字节都有一个独一无二的虚拟地址,这个虚拟地址的作用就是作为数组的下标。磁盘中的数组内容在主内存中进行缓存。和内存体系中的其他缓存一样,在磁盘(低层次)上的数据会被划分成数据块(block),划分的作用是在磁盘和主存(高层次)间作为传输单位。虚拟内存系统通过将虚拟内存划分为固定大小称为虚拟页的(virtual pages,VPs)块来完成这个过程。每个虚拟页的大小都为 P = 2 p P=2^p P=2p字节。相似地,物理内存也被划分为物理页(physical pages,PPs),每个页的大小同样为P字节。注意,物理页有时候也被称为物理帧(page frames)。
在任意时间点,虚拟页集合都会被划分为如下的三个不相交的子集:
- 未分配(unallocated):这代表还没有被虚拟内存系统分配(或创建)的页。未分配的块没有和任何数据联系在一起,因此在磁盘中没有占据空间
- 已经缓存的(cached):已经分配的页并且已经在物理内存中进行了缓存
- 未缓存的(uncached):已经分配的页,但是还没有在物理内存中进行缓存
图9.3中的例子展示了一个有八个虚拟页的小虚拟内存区域(注意页表总数为
2
n
−
p
2^{n-p}
2n−p):
其中虚拟页0和虚拟页3还没有被分配,因此在磁盘中还不存在。虚拟页1、4和6已经在物理内存中进行了缓存。虚拟页2、5和7已经被分配了,但是还没有在主内存中进行缓存。
3.1 DRAM缓存的组织方式
为了使得内存层次的表达不混淆,使用术语SRAM缓存指代CPU和主存间的L1、L2和L3缓存。使用术语DRAM缓存表示虚拟内存系统中在主存中缓存虚拟页的缓存。
DRAM缓存在内存层次中的位置对它的组织形式有很大的影响。DRAM大概比SRAM慢10倍,而磁盘要比DRAM慢10000倍。因此,DRAM缓存中的缺失要比SRAM缓存中的缺失严重很多。此外,从一个磁盘扇区中读取第一个字节的速度比读取后续字节慢了10000倍。
因为大量内存缺失及访问磁盘第一个字节带来的开销,虚拟内存倾向于设计的很大。通常会被设置为4KB及2MB之间。由于内存缺失的影响太过严重,DRAM缓存被设置为全连接的,这代表着任何一个虚拟页都可以放到任何一个物理页中。缺失时执行的替换政策同样很重要,因为如果替换了错误的页,那么后续的效率损失很大。因此,操作系统会对DRAM缓存使用一种十分复杂的页置换方式(远比SRAM缓存复杂,超出了介绍范围)。最终,由于访问磁盘需要大量的时间,DRAM缓存通常使用write-back而不是write-through。
3.2 页表
和其他缓存一样,虚拟内存系统需要有某种方式来判断一个虚拟页是否在DRAM的某处进行了缓存。系统还需要判断它缓存到了那个物理页中。如果存在缺失,那么系统需要判断这个虚拟页存储在物理磁盘的哪个位置,选择物理内存中的待替换页,并将虚拟页从磁盘中复制到DRAM中,替换待替换页。
这些功能的实现通过操作系统软件,MMU中的地址翻译硬件及存储在物理内存中称为页表的将虚拟页映射到物理页的数据结构的组合来实现。地址翻译硬件在每一次将虚拟地址转化为物理地址时进行地址的翻译。操作系统负责维护页表的内容以及在磁盘和DRAM间进行页的转移。
图9.4展示了页表的基本组织形式:
页表由页表实体(page table entries,PTEs)组成。虚拟地址空间中的每一页都在页表中某个固定的偏移量中有一个PTE。我们假设PTE包含一个有效位(valid bit)以及一个n位地址域(address field)。有效位指示了虚拟页是否现在在DRAM进行了缓存。如果有效位置位,那么地址域会指明虚拟页缓存到的DRAM中的对应物理页。如果有效位没有置位,那么一个空地址会指明这个虚拟页还没有被分配。否则,地址会指向在磁盘中这个虚拟页的开始。
图9.4中展示的页表中,存在8个虚拟页以及4个物理页。四个虚拟页(VP 1,VP 2,VP 4和VP 7)已经在DRAM中进行了缓存。两个页(VP 0和VP 5)还没有被分配,其他的两个(VP3和VP6)已经被分配了,但是还没有进行缓存。图9.4中需要注意的很重要的一点是DRAM缓存是全连接的,任何一个物理页都可以包含任意一个虚拟页。
3.3 页命中
考虑当CPU从虚拟内存VP2中读取一个字大小的数据时发生了什么(这个数据在DRAM中进行了缓存,如图9.5所示):
地址翻译硬件使用虚拟地址作为定位PTE2的下标,并且从内存中将它读出。因为有效位已经置位,地址翻译硬件知道了VP2已经在内存中进行了缓存。所以它使用PTE中的物理内存地址(这个地址指向缓存页PP1的开始地址)来构建这个字的物理地址。
3.4 页缺失
缺少DRAM缓存被称为页缺失。图9.6展示了一个在页缺失前页表的状态例子:
CPU引用了VP3中的一个字,但是这个字并没有在DRAM中进行缓存。地址翻译硬件会从内存中读取PTE3,但是状态位没有置位,说明VP3没有被缓存,这就会出发一次缺页异常。
缺页异常会调用页系统内核中的缺页异常处理器,这个处理器会选择一个待替换页(victim page),在这个例子中是PP3中存储的VP4。如果VP4被修改过,那么系统会将它的值写回磁盘中。否则,内核回修改VP4的页表项,指明VP4不再在主存中进行缓存。
接下来,内核从磁盘中拷贝出VP3中的内容到内存中的PP3内,并更新PTE 3,接下来返回。当处理器返回时,它会重启引发缺页异常的指令。此时VP3已经在主存中进行了缓存,因此地址翻译硬件会进行一次常规的页命中。图9.7展示了例子页命中后的页表:
虚拟内存在60年代早期发明,这远远早于CPU和内存间逐渐扩大的差距催生出的SRAM的产生。因此,虚拟内存系统使用了一种和SRAM缓存完全不同的技术,尽管很多思想是类似的。对虚拟内存来说,块被称为页。将一个页从磁盘中移动到内存的过程称为页交换(swapping)或分页(paging)。页被从磁盘交换(或分页)到DRAM中,并且被从磁盘交换出(或分页出)磁盘中。等到一个缺失发生时才换入一个页的策略称为需求分页(demanding page)。还有其他的分页策略,例如尝试预测可能会发生的缺页并且在这些页被引用前进行交换。但是,所有现代的系统都使用需求分页。
3.5 分配页
图9.8显示了当操作系统分配一个新的虚拟内存页时对页表的影响,例如我们调用了malloc:
在这个例子中,VP5通过在磁盘中分配空间并且更新PTE5指向新创建的磁盘页中完成。