x86 上使用的解决方案是使用“稀疏”页表,即没有一个完整的表来包含每个页面的映射。而是使用了两级机制:
虚拟内存为4 GB 很大。单个页面的大小为4 KB。因此,使用一级方法将需要一个包含4 GB / 4 KB = 1024 * 1024 条目的表。如果一个条目占用 4 个字节,那么每个进程都需要 4 MB 来存储它的表。
使用a two level approach,我们有一个页面目录,其中包含1024 个条目,每个条目大小为4 字节(使其完全适合单个4 KB 页面)。因此,该目录中的每个条目都管理4 GB / 1024 = 4 MB。如果(且仅当)在4 MB 范围内应该有一些虚拟内存页面到物理内存的映射,那么条目指向另一个结构的实例,即页表。这也包含 1024 个条目,因此每个条目都管理 4 MB / 1024 = 4 KB 正好一页。
如果有一个进程只需要一个页面来操作,那么使用单级方法我们需要4 MB 来存储它的虚拟内存配置。使用上述两级机制,我们需要4 KB 用于页面目录,4 KB 用于包含该单个页面映射的页表。因此只有8 KB 用于存储虚拟内存配置。
如果进程在运行时需要额外内存,并且该内存位于(虚拟)地址不在其页表管理的4 MB 范围内,则需要提供第二个页表,从而增加使用的内存通过另一个4 KB 存储映射。
使用这种两级方法略微增加了对不在 TLB 中的页面的访问时间,因为内存管理单元需要访问两个内存位置(页面目录,然后是相应的页表)才能计算物理地址.
TLB 不受此影响:它存储单个页面的映射。这些映射是如何建立的与其操作无关。
让我们将它应用到您上面给出的示例配置中:
单个页面的大小为1 KB。正如您所说,大多数进程将具有256 KB 或更少的内存。但是我们希望能够让进程使用更多的虚拟内存。
如果我们选择让最后一层处理完整的256 KB,那么我们有
256 KB / 1 KB = 256 条目。假设32 bit 架构,这反过来意味着我们可以让每个条目的大小为4 byte(以保存地址)。 256 entries * 4 Byte = 1 KB 和整页。不错。
为了能够处理比256 KB 更多的虚拟内存,我们添加了另一层。因为这很简单,我们让这个级别也使用具有 256 个条目(4 字节)的表格,以使这样的表格完全适合页面。
这为我们提供了256 * 256 KB(大致为65 MB)的虚拟内存。该系统中的虚拟地址将是26 bit long:
DDDDDDDDTTTTTTTTPPPPPPPPPP
D := Index to page directory, highest level.
8 bit to be able to index 256 entries.
T := Index to page table, lower level.
8 bit to be able to index 256 entries.
P := Offset inside page.
10 bit to be able to address 1024 bytes.
使用少于256 KB 的进程需要2 KB 来管理其内存配置。每增加一个256 KB 的虚拟内存,就需要再增加一个1 KB 的配置内存。
假设 TLB 可以容纳 128 个条目(您的问题在这里有点不清楚)它需要128 * (16 + X - 10) bit,其中X 是用于寻址物理内存的位数。 (虽然这取决于实际的实现。我在考虑每个条目的16 bit 来存储分页结构的索引+物理地址的高位,不计算 10 位偏移量)
我希望这能回答您的问题。实际的实现需要根据很多约束做出设计选择。