我对一些概念感到困惑,需要有人帮我澄清一下。
我知道在执行期间,有一部分程序存储在硬盘上,也就是虚拟内存中,对吗?!虚拟内存被分成称为“页面”的数据块,在分页系统中,这些页面具有固定大小(如 4KB),其中一些页面被映射(即存在并加载到主内存中)到实际物理地址并存储在固定大小的数据块中(与页面大小相同,例如 4KB),这些数据块称为页框“或仅页框”,
现在,虚拟内存和物理内存之间有一个映射表,对吗?!并且还有一个由 CPU 生成的逻辑地址,它被映射到实际物理内存地址,对吗?!因此,页面映射和逻辑地址映射是两个不同的东西,但是它们的工作原理是否相同,对吗?!
注意:到目前为止,如果我错了,我需要有人来纠正我!!
现在,当程序想要使用存储在磁盘(页面)上但未映射到内存(帧)中的数据时,内存需要进行页面替换,对吗?!
例如,它使用最佳页面替换算法,现在我们知道(如果为真)物理内存中有一个帧,每个帧都有一个字节大小,(就像包含一系列表示程序指令的字节的数据块,对吧?!)如果程序要求未映射到内存中的数据(页面错误)并且需要使用最佳算法进行页面替换,那么我知道我的下一个问题很愚蠢,因为页面替换很清楚它替换了一个完整的页面,但它真的替换了一个完整的页面还是页面内的字节(即页面框架)因为我在下面的视频中看到了这个例子,我对他在视频开头所说的内容感到困惑,我们有大小为 3 的帧(而不是内存中的 3 个帧),他开始替换大小为 3 的页面内的页面,我的意思是替换 3 个页面你应该在物理内存中有 3 个相应的页面,对吧?!
请问我需要有人告诉我刚才发生了什么,因为我理解该算法的工作原理,但对他使用的概念有疑问!!
视频 : https://www.youtube.com/watch?v=uYcVtK65KHk
附言:抱歉解释得太长了,而且我的英语不好,
亲切的问候
答案1
免责声明:本回答的大部分内容(尤其是部分术语)以 Windows 为中心,并以 x86/x64 为中心。大部分概念适用于大多数其他通用虚拟内存操作系统和大多数其他平台,但细节和部分术语会有所不同。
程序的一部分在执行期间存储在硬盘上,也就是虚拟内存上,对吗?!
呃,是的,但这并不是 VM 的全部。(注:本答案中的“VM”始终表示“虚拟内存”,而不是“虚拟机”。)在典型的 VM 环境中,程序 + 操作系统的整个地址空间被视为位于虚拟内存中。
在任何时候,虚拟内存的一个子集都是“常驻”的,即“位于 RAM 中,可以引用而不会导致页面错误”。其余大部分位于“辅助存储”中,如今,辅助存储几乎总是磁盘或 SSD。(专门用于保存非常驻虚拟内存的“辅助存储”的另一个名称是“后备存储”。)
虚拟地址空间还有第三个子集,即位于 RAM 中但需要页面错误才能访问的内容 - 在 Windows 中,这可能是已修改或备用页面列表中的页面,或者是已在 RAM 中供其他进程使用但对于发生错误的进程而言尚未生效的共享页面。还有“需求零”错误。所有这些都是“软错误”的示例,即不涉及磁盘读取的错误。我不会在这里讨论这些情况,因为无论如何这都会是一个很长的答案,而且它们与您的问题无关:它们都不涉及页面替换。
虚拟内存被划分为称为“页面”的数据块,在分页系统中,这些页面具有固定大小(例如 4KB),其中一些页面被映射(即存在并加载到主内存中)到实际物理地址并存储在固定大小的数据块中(与页面大小相同,例如 4KB),这些数据块称为页框“或仅帧”
被称为“页框”的是 RAM 的页面,而不是其内容(即不是数据)。另外顺便说一句,分页带来的不仅仅是数据,还有程序的代码。
虚拟内存和物理内存之间有映射表吗?
是的。它们被称为页表。更好的理解方式是,页表在虚拟页号和物理页号(又称页框号)之间进行映射。也就是说,它们允许地址翻译从虚拟地址到物理地址。
顺便说一句:我们认为常驻的东西仍然是“虚拟的”,因为我们用来引用它的地址仍然必须转换为物理地址。即使是常驻的东西,其物理位置也可能随时改变。
并且还有一个逻辑地址是由 CPU 生成的,并映射到实际的物理内存地址,对吗?因此,页面映射和逻辑地址映射是两个不同的事情,但是它们的工作原理却相同,对吗?
“逻辑地址”和“线性地址”都是通常与 x86 分段寻址相关的术语。(或者像我们这些自 70 年代以来一直生活在平面地址空间中的人所说的那样,“疯狂寻址”。)“逻辑地址”由来自指令操作数的“位移”或“偏移量”以及该操作数隐式或显式使用的“内存段”的基址组成。有六个可能的段,称为 C(用于代码,隐式用于引用指令流的任何内容,如 CALL 和 JMP 指令)、D(用于数据,隐式用于大多数非代码引用)、S(用于堆栈,隐式用于涉及堆栈指针寄存器的引用),以及三个“额外”段,E、F 和 G,可用于任何您想要的用途。操作数编码允许您在某些情况下覆盖默认段。MMU 将位移与段的基址相加,形成“线性地址”。
实际上,在现代操作系统中,分段几乎被禁用 - 我的意思是几乎所有段(F 和 G 段除外)的基址都是 0,因此指令操作数断言的“位移”就变成了线性地址。当 CPU 中打开“分页”时(这在操作系统启动的很早的时候就会发生,并且在操作系统运行时永远不会关闭),线性地址就会通过页表转换为虚拟地址。因此,在 VM 操作系统中,我们实际上不会考虑“线性地址”。位移与线性地址相同,与虚拟地址相同,我们只考虑虚拟地址。
顺便说一句,AMD 的 x64 设计师在咨询了各种操作系统的内核工程师后,几乎完全省略了分段机制......除了 F 和 G 段,Windows 和其他操作系统使用它们来定位关键操作系统数据结构。
在操作系统中,我们的思维方式是:CPU 在 VM 环境中执行指令时总是通过虚拟地址引用内存。虚拟地址由虚拟页号和页内的字节偏移量组成,后者是低 12 位。CPU 的内存管理单元 (MMU) 在页表中查找虚拟页号到物理页号的转换。如果页表条目 (PTE) 没有设置“有效”位,则意味着该页面不是“常驻”的,处理器会引发页面错误异常。操作系统的分页器是该类异常的异常处理程序。如果可能,它会解决故障,产生有效的 PTE,然后消除异常。然后处理器重新执行引发故障的指令 - 但这一次,它不会引发故障。
现在,当程序想要使用存储在磁盘(页面)上但未映射到内存(帧)中的数据时,内存需要进行页面替换,对吗?!
不一定。解决“硬”页面错误通常包括以下几项优化:
- 确定所需页面的内容存储在磁盘上的什么位置
- 找到 RAM 的可用物理页面并将其分配给故障进程
- 将磁盘内容读入可用页面
- 更新页面位置的页表项,并设置“有效”位
- 消除页面错误异常
步骤 2 可能涉及页面替换,但更常见的是使用当前未使用的页面。典型的 VM OS 维护此类页面的列表。
它真的替换了整整一页还是页内的字节(即页框)因为我在下面的视频中看到了这个例子并且我对他在视频开头所说的内容感到困惑我们有大小为 3 的框(而不是内存中的 3 个框)并且他开始替换大小为 3 的页面内的页面我的意思是替换 3 个页面你应该在物理内存中有 3 个相应的页面对吗?!
在我上面列出的步骤 3 中,目标页面总是被全部覆盖。坦白说,我不知道“替换页面大小为 3 内的页面”是什么意思。
现在,我上面提到的优化之一是,如果你需要虚拟页面n现在,你可能需要虚拟页面n+1 等等。因此传呼机通常会做一定数量的预读,一次读取多页。是的,如果您要读取三页,则需要处理物理内存中的三页。它们不一定是连续的,无论是在工作集列表中还是在物理 RAM 地址方面。事实上,虚拟内存的一大好处是,对连续可用虚拟内存的担忧基本上消失了。
参考:
内存管理章节Windows 内部原理由 Solomon、Russinovich 和 Ionescu 编写 - 任何版本,因为以上内容均不特定于 Windows 版本。
Intel® 64 和 IA-32 架构软件开发人员手册、第 3A 卷(“系统编程”)、第 3 章(“保护模式内存管理”)和第 4 章(“分页”)。