此处解释了分页,幻灯片 #6:
http://www.cs.ucc.ie/~grigoras/CS2506/Lecture_6.pdf
在我的讲义中,但我终生无法理解。我知道这是一种将虚拟地址转换为物理地址的方法。因此,磁盘上的虚拟地址被分成 2^k 的块。在这之后我真的很困惑。有人可以简单地向我解释一下吗?
此处解释了分页,幻灯片 #6:
http://www.cs.ucc.ie/~grigoras/CS2506/Lecture_6.pdf
在我的讲义中,但我终生无法理解。我知道这是一种将虚拟地址转换为物理地址的方法。因此,磁盘上的虚拟地址被分成 2^k 的块。在这之后我真的很困惑。有人可以简单地向我解释一下吗?
正如您所指出的,分页是一种虚拟内存。回答@John Curtsy 提出的问题:它通常与虚拟内存分开讨论,因为还有其他类型的虚拟内存,尽管分页现在(到目前为止)是最常见的。
分页虚拟内存非常简单:您将所有物理内存分成块,大部分大小相同(尽管在实践中选择两个或三个大小是相当普遍的)。使块大小相等使它们可以互换。
然后你有寻址。您首先将每个地址分成两部分。一个是页面内的偏移量。您通常使用该部分的最低有效位。如果您使用(例如)4K 页面,则需要 12 位作为偏移量。使用(比如说)32 位地址空间,剩下 20 位。
从那里开始,事情确实比最初看起来要简单得多。您基本上构建了一个小的“描述符”来描述每一页内存。这将有一个线性地址(客户端应用程序用来寻址该内存的地址),一个内存的物理地址,以及一个 Present 位。将(至少通常)还有一些其他的东西,比如指示该页面中的数据是否可以读取、写入、执行等的权限。
然后,当客户端代码使用地址时,CPU 会从地址的其余部分分解页面偏移量开始。然后它获取线性地址的其余部分,并查看页面描述符以找到与该线性地址相关的物理地址。然后,为了寻址物理内存,它使用物理地址的高 20 位和线性地址的低 12 位,它们一起形成实际的物理地址,从处理器引脚上发出并从内存芯片中获取数据.
现在,我们到了获得“真实”虚拟内存的部分。当程序使用的内存多于实际可用内存时,操作系统会获取其中一些描述符的数据,并将其写入磁盘驱动器。然后它清除该内存页的“Present”位。内存的物理页现在可用于其他用途。
当客户端程序尝试引用该内存时,CPU 会检查 Present 位是否已设置。如果不是,CPU 会引发异常。发生这种情况时,CPU 会像上面那样释放一块物理内存,从磁盘读回当前页面的数据,并用它现在所在的物理页面的地址填充页面描述符。完成所有这些后,它从异常中返回,CPU 重新开始执行导致异常开始的指令——除了现在,Present 位被设置,因此使用内存将起作用。
您可能还需要了解一个细节:页描述符通常排列在页表中,并且(重要的部分)您通常为系统中的每个进程拥有一组单独的页表(另一个用于 OS 内核本身)。为每个进程拥有单独的页表意味着每个进程可以使用相同的线性地址集,但它们会根据需要映射到不同的物理地址集。您还可以通过创建两个包含相同物理地址的单独页面描述符(每个进程一个)将相同的物理内存映射到多个进程。大多数操作系统都使用它,例如,如果您有两个或三个相同程序的副本正在运行,它实际上只有一个该程序的可执行代码在内存中的副本——但它会有两到三组指向同一代码的页面描述符,因此它们都可以使用它,而无需为每个单独的副本。
当然,我简化了很多——已经写了很多关于虚拟内存的完整(而且通常是相当大的)书籍。机器之间也有相当多的变化,添加了各种装饰,对参数进行了微小的更改(例如,页面是 4K 还是 8K)等等。尽管如此,这至少是对所发生事情的核心的一般概念(并且它仍然处于足够高的水平,可以同样适用于ARM、x86、MIPS、SPARC 等)
简而言之,它是一种保存比您的地址空间通常允许的更多数据的方式。即,如果您有 32 位地址空间和 4 位虚拟地址,则可以保存 (2^32)^(2^4) 个地址(远远超过 32 位地址空间)。