把主存空间划分为大小相等且固定的块,块相对较小,作为主存的基本单位。
每个进程也以块为单位进行划分,进程在执行时,以块为单位逐个申请主存中的块空间。
分页的方法从形式上看,像分区相等的固定分区技术,分页管理不会产生外部碎片。
为方便地址转换,页面大小应是2的整数幂。
同时页面大小应该适中
页面过大又会使页内碎片增多,降低内存的利用率。
简称为地址结构
页号P
页内偏移W
地址结构决定了虚拟内存的寻址空间有多大
为了便于在内存中找到进程的每个页面所对应的物理块,系统为每个进程建立一张页表
在配置页表后,进程执行时,通过查找该表,即可找到每页在内存中的物理块号。
可见,页表的作用是实现页号到物理块号的映射
页表是由页表项组成的

地址变换机构的任务是将逻辑地址转换为物理地址
地址变换借助于页表(page table,简单记为PT或T)实现
在系统中通常设置一个页表寄存器(PTR(page table register)),存放以下内容(2个字段):
进程未执行时,页表的始址和页表长度存放在本进程的PCB中
进程被调度执行时,才将页表始址和页表长度装入页表寄存器PTR中
设页面大小为 L L L🎈
需要被计算物理地址的*某个字的*逻辑地址为 A A A🎈
A对应的到物理地址E🎈
A → E A\to{E} A→E的变换过程如下(记为函数(映射)E: E = E ( A ) E=E(A) E=E(A))
由给定的逻辑地址A计算对应的页号和页内偏移量
比较页号P和页表(每个进程都有自己的页表)长度M
页表中:
记:页号P对应的页表项地址为 T . P T.P T.P
T . P = F + P × L T.P=F+P\times{L} T.P=F+P×L
最后计算 E = b L + W E=bL+ W E=bL+W,用得到的物理地址E去访问内存(具体的存储单元)
以上整个地址变换过程均是由硬件自动完成的。

观察改过程,可以发现比其仅包含慢表的地址变换机构,包含快表的地址变换机构多了快表这条高速路径,快速计算出物理块号b,从而通过E=bL+W得到物理地址
若页表全部放在内存中,则存取一个数据或一 条指令至少要访问两次内存:
在具有快表的分页机制中,地址的变换过程如下:
由地址转换过程可知,访存时先访问一次主存去查页表,再访问主存才能取得数据。
依据程序执行的局部性原理,在一段时间内总是经常访问某些页时,若把这些页对应的页表项存放在高速缓冲器组成的快表(TLB)中,则可以明显提高效率。
TLB:Translation Lookaside Buffer
页表缓存
转址旁路缓存
转译后备缓冲器
目前所有的桌面型及服务器型处理器(如 x86)皆使用TLB。
其搜索关键字(输入为虚拟内存地址,其搜索结果(输出)为物理地址。
如果请求的虚拟地址在TLB中存在,CAM 将给出一个非常快速的匹配结果,之后就可以使用得到的物理地址访问存储器。
如果请求的虚拟地址不在 TLB 中(未命中),就会使用标签页表(分页表/慢表(普通页表))进行虚实地址转换
A translation lookaside buffer (TLB) is a memory cache that stores the recent translations of virtual memory to physical memory.
It is used to reduce the time taken to access a user memory location.[1]
It can be called an address-translation cache.
It is a part of the chip’s memory-management unit (MMU).
A TLB may reside between the CPU and the CPU cache, between CPU cache and the main memory or between the different levels of the multi-level cache.
The majority of desktop, laptop, and server processors include one or more TLBs in the memory-management hardware, and it is nearly always present in any processor that utilizes paged or segmented virtual memory.
The TLB is sometimes implemented as content-addressable memory (CAM).
TLB 用于缓存一部分标签页表条目。
TLB可介于CPU和 CPU缓存之间,或在CPU、缓存和主存之间,这取决于缓存使用的是物理寻址或是虚拟寻址。
相应地把放在主存中的页表称为慢表(普通页表)(Page Table)。
在地址转换时,首先查找快表,若命中,则无须访问主存中的页表。
快表通常采用全相联或组相联方式。
每个TLB项由页表项内容加上一个TLB标记字段组成,
两级页表(Two-Level Page Table)
针对难于找到大的连续的内存空间来存放页表的问题,可利用将页表进行分页的方法
使每个页面的大小与内存物理块的大小相同,并为它们**进行编号,**即依次为0#页、1#页,…n#页,
然后离散地将各个页面分别存放在不同的物理块中。
同样,也要为离散分配的页表再建立一张页表,称为外层页表(Outer Page Table)
页表分页:保存页表(页表项形式)的页面
下面我们仍以前面的32位逻辑地址空间为例来说明。
当页面大小为4KB时(12位),若采用一级页表结构,应具有30-12=20位的页号,即页表项应有1M个;
每个页面的容量为 4 K B 4KB 4KB,每个页表项大小为4B,则每个页面可以容纳 4 K B 4 B = 1 K = 1024 \frac{4KB}{4B}=1K=1024 4B4KB=1K=1024个页表项
保存页表项的页面需要 1 K = 1 M 1 K 1K=\frac{1M}{1K} 1K=1K1M个
在采用两级页表结构时,再对页表进行分页,使每页中包含 2 10 2^{10} 210(即1024)个页表项
(外层页)最多允许有 2 10 2^{10} 210个页表分页(对应于 2 10 2^{10} 210个页表项)
外层页面数控制在一个
否则使得顶级页表页数超过一个页面,不符合使用习惯(查询不便),超出这个数值需要再建立高级页表
或者说,外层页表中的外层页内地址字段 P 2 P_2 P2为10位,外层页号 P 1 P_1 P1也为10位。
此时的逻辑地址结构
| 外层页号( P 1 P_1 P1) | 外层页内地址 P 2 P_2 P2 | 页内地址d |
|---|---|---|
| 10bit | 10bit | 12bit |
页表中的页表项总是由:逻辑页号,物理块号 构成
由图可以看出,
(内层)页表的每个表项中,存放的是进程的某页在内存中的物理块号,
外层页表的每个页表项中所存放的是某页表分页的首址,
我们可以利用外层页表和页表这两级页表来实现进程从逻辑地址到内存中物理地址的变换。

上述对页表施行离散分配的方法,虽然解决了对于大页表无需大片连续存储空间的问题
但并未解决用较少的内存空间去存放大页表的问题
换言之,只用离散分配空间的办法并未减少页表所占用的内存空间。
能够用较少的内存空间存放页表的唯一方法是
仅把当前需要的一批页表项调入内存,以后再根据需要陆续调入。
在采用两级页表结构的情况下,对于正在运行的进程,必须将其外层页表调入内存,而对于页表则只需调入一页或几页。
为了表征某页的页表是否已经调入内存,还应在外层页表项中增设一个状态位S,其值若为0,表示该页表分页不在内存中,否则说明其分页已调入内存。
进程运行时,地址变换机构根据逻辑地址中的P,去查找外层页表:
以某个需要40MB内存的进程(系统分配给该进程共40MB)的内存(页框)为例,体会进程的页表可能占用掉相当客观的内存
为了减少载入内存中的页表占用空间,我们进一步延伸页表映射的思想,就可得到二级分页,即使用层次结构的页表:
| 1级(顶级)页号字段(页目录号) | 2级页号字段 | … | k级字段 | 页内偏移 |
|---|
在进程执行时,只需要将这一页的上一级页表调入内存即可
进程的页表和进程本身的页面可在后面的执行中再调入内存。
根据上面提到的条件(32位逻辑地址空间、页面大小4KB、页表项大小4B,以字节为编址单位),我们来构造一个适合的页表结构。
页面大小为4KB
若不采用分级页表,且映射全部的地址空间,共有 2 20 2^{20} 220个页面,相应地需要 2 20 2^{20} 220个页表项记录,每个页表项又是占用4B,页面大小为4KB,则仅这些页表项页表就要占用 2 20 × 4 B / 4 K B = 1024 2^{20}\times4B/4KB = 1024 220×4B/4KB=1024 页,这大大超过了许多进程自身需要的页面,对于内存来说是非常浪费资源的
若不把这些页表放在连续的空间里,则需要一张索引表来告诉我们第几张页表该上哪里去找,这能解决页表的查询问题,且不用把所有的页表都调入内存,只在需要它时才调入(下节介绍的虚拟存储器思想),因此能解决占用内存空间过大的问题。
🎈为查询方便,顶级页表(代表力权重最高的页面)最多只能有1个页面(一定要记住这个规定),
对于本例而言,无论划分为多少级页表,顶级页表(1级页表)总共可以容纳4KB/4B = IK个页表项,它占用的地址位数为 log 2 1 K = 10 \log_2{1K}= 10 log21K=10 位
而之前已经计算出页内偏移地址占用了12 位,因此一个32位的逻辑地址空间就剩下了10 (32-10-12=10)位,正好使得二级页表的大小在一页之内, 这样就得到了逻辑地址空间的格式
| 1级页号 | 2级页号 | 页内偏移 |
|---|---|---|
| 10 | 10 | 12 |
某计算机采用二级也报的分页存储管理方式
按照字节编址
页面大小为L§= 2 10 2^{10} 210B
页表项大小L(I)=2B
逻辑地址空间大小为 2 16 2^{16} 216
逻辑地址结构为:
| 页目录号 | 页号 | 页内偏移 |
|---|
表示整个逻辑地址空间的页目录表中包含的表项个数N至少是?
分析:
有效访问时间(Effective Access Time,EAT):访问内存的有效时间
可以用来分析引入快表后访存性能相对于仅有慢表的情况下的提升情况.
从进程发出指定逻辑地址的访问请求,以下过程所需要花费的总时间,称为内存的有效访问时间(Effective Access Time,EAT)。
假设访问一次内存的时间为t,在基本分页存储管理方式中,有效访问时间分为
E A T = t + t = 2 t EAT=t+t=2t EAT=t+t=2t
在引入快表的分页存储管理方式中,通过快表查询,可以直接得到逻辑页所对应的物理块号,由此拼接形成实际物理地址,减少了一次内存访问,缩短了进程访问内存的有效时间。
设:
δ \delta δ表示查找快表所需要的时间,
a a a表示命中率,
t t t表示访问一次内存所需要的时间
每次放存都先访问一次快表
这样,在引入快表的分页存储管理方式中,有效访问时间的计算公式即为:
E A T = a ( t + δ ) + ( 1 − a ) ( 2 t + δ ) 或 E A T = t a + t = [ a δ + ( 1 − a ) ( δ + t ) ] + t 化 简 后 都 等 于 2 t − a t + δ 即 E T A = 2 t − a t + δ = t ( 2 − a ) + δ EAT=a(t+\delta)+(1-a)(2t+\delta) \\ 或 \\EAT=t_a+t=[a\delta+(1-a)(\delta+t)]+t \\化简后都等于2t-at+\delta \\即ETA=2t-at+\delta=t(2-a)+\delta EAT=a(t+δ)+(1−a)(2t+δ)或EAT=ta+t=[aδ+(1−a)(δ+t)]+t化简后都等于2t−at+δ即ETA=2t−at+δ=t(2−a)+δ
在命中率极高的情况下, E T A ≈ t + δ ETA\approx{t+\delta} ETA≈t+δ,相比于基础地址转换机构的时间 t b = 2 t t_b=2t tb=2t,由于访问快表非常快,所以 δ \delta δ很小那么最好的情况下可以少掉一次访存时间 ∣ Δ ∣ = ∣ ( E T A − t b ) ∣ → t |\Delta|=|(ETA-t_b)|\to{t} ∣Δ∣=∣(ETA−tb)∣→t