【问题标题】:Virtual memory in OS操作系统中的虚拟内存
【发布时间】:2018-03-10 16:01:17
【问题描述】:

我一直在尝试理解正在运行的程序使用的虚拟地址空间概念。让我以在 32 位 Windows 操作系统上运行的 32 位应用程序为例。

据我所知,每个进程都认为(或“认为”)自己是系统上运行的唯一应用程序(这是正确的吗?)并且它可以访问 4GB 地址,在标准配置中,2GB分配给内核,2分配给用户进程。我对此有以下疑问:

  1. 为什么用户进程需要在其地址空间中加载内核代码?为什么内核不能拥有自己完整的 4GB 地址空间,让每个进程都能享受 4GB 空间?

  2. 在 2GB+2GB 配置中,2GB 是否足以让内核加载其所有代码?构成内核的所有应用程序代码肯定都(或可能)超过 2GB 吗?同样,如果考虑到它自己的代码以及 dll 等其他依赖项,分配了 2GB 地址空间的用户进程肯定需要超过 2GB 的空间?

  3. 我对这个主题的另一个问题是关于计算机系统上存在正在运行的进程的各个位置 - 例如,我有一个程序 C:\Program Files\MyApp\app.exe。当我启动它时,它使用虚拟地址空间加载到进程中,并使用分页 (pagefile.sys) 来使用有限的 RAM。我的问题是,一旦 app.exe 启动,它是全部加载到 RAM+Pagefile 中还是只从 C:\Program Files\MyApp\myapp.exe 加载程序的一部分,因此它继续引用exe 位置在需要时获取更多信息?

  4. 最后一个问题 - 在 32 位操作系统上,如果我的 RAM 超过 4 GB,内存管理是否可以使用超过 4 GB 的 RAM 空间,否则会浪费?

谢谢 史蒂夫

【问题讨论】:

    标签: virtual-memory


    【解决方案1】:

    为什么用户进程需要在其地址中加载内核代码 空间?为什么内核不能拥有自己完整的 4 GB 地址空间 每个进程可以享受4GB空间?

    一个进程可以有(略少于)4 GiB。问题在于将虚拟地址转换为物理地址的成本很高,因此 CPU 使用“translation look-aside buffer”(TLB)来加速;并且(至少在较旧的 CPU 上)更改虚拟地址空间(例如,因为内核在其自己的虚拟地址空间中)导致 TLB 条目被丢弃,这导致(虚拟)内存访问变慢(因为“TLB 未命中” )。将内核映射到所有虚拟地址空间可以避免/避免这个性能问题。

    注意:对于具有“PCID”功能的现代 CPU,可以通过给每个虚拟地址空间一个 ID 来避免性能问题;但大多数操作系统是在此功能出现之前设计的,因此(即使有崩溃补丁)它们仍然以相同的方式使用虚拟地址空间。

    在 2GB+2GB 配置中,2GB 足以让内核加载其所有 代码?当然,构成内核的所有应用程序代码更多 超过2GB?同样,分配了 2GB 地址的用户进程 当您将自己的代码视为时,空间肯定需要超过 2 GB 以及其他依赖项,例如 dll?

    代码从来都不是问题——它的数据。一般来说,大多数软件要么不需要 2 GiB 的空间,要么需要超过 4 GiB 的空间;很少需要 2 GiB 但不需要超过 4 GiB。对于需要超过 4 GiB 空间的东西,大约 10 年前,一切都转移到了 64 位(通常使用 131072 GiB 或更多的“用户空间”),所以......

    我的问题是,一旦 app.exe 启动,它是完全加载到 RAM+Pagefile 中还是只从 C:\Program Files\MyApp\myapp.exe 加载程序的一部分,因此它会继续运行在需要时参考 exe 位置以获取更多信息?

    大多数现代操作系统都使用“内存映射文件”。这个想法是可执行文件最初根本没有加载到 RAM 中,但是如果/当第一次实际访问页面中的某些内容时,它会导致“页面错误”并且页面错误处理程序从磁盘获取页面。这往往会减少 RAM 消耗(未访问的内容永远不会从磁盘加载)并缩短进程启动时间。

    在 32 位操作系统上,如果我有超过 4 GB 的 RAM,内存管理可以使用超过 4 GB 的 RAM 空间还是浪费?

    有多个虚拟地址空间,其中虚拟地址可能为 32 位宽,而单个物理地址空间(取决于 CPU 支持的扩展)物理地址可能为 36 位宽(甚至更宽)。这意味着您可以在“仅 32 位”CPU 上运行 32 位操作系统,该 CPU 可以有效地使用(例如)64 GiB 的 RAM(如果您能找到真正支持它的主板)。在这种情况下,CPU 仍然将虚拟地址转换为物理地址,进程不需要知道物理地址的大小;但单个进程无法单独使用所有 RAM(您需要许多进程才能使用所有 RAM)。

    【讨论】:

      【解决方案2】:

      为什么用户进程需要在其地址空间中加载内核代码?为什么内核不能拥有自己完整的 4GB 地址空间,让每个进程都可以享受 4GB 空间?

      通常没有内核进程(NULL 进程除外)。大多数 CPU 的进程异常和中断都在当前运行进程的上下文中。为了支持这一点,内核需要位于同一位置并在所有进程中具有相同的布局。否则,在一个进程中发生的中断的处理方式与在另一个进程运行时发生的中断的处理方式不同。

      在 2GB+2GB 配置中,2GB 是否足以让内核加载其所有代码?构成内核的所有应用程序代码肯定都(或可能)超过 2GB 吗?同样,如果考虑到它自己的代码以及 dll 等其他依赖项,分配了 2GB 地址空间的用户进程肯定需要超过 2GB 的空间?

      你在这里有误解。内核空间中没有应用程序代码。内核空间代码仅在响应中断或异常时执行。

      2GB 对于我见过的任何内核都绰绰有余。事实上,一些 32 位系统(在硬件允许的情况下)使内核空间小于 2GB,并相应地增加了用户空间的大小。

      我对这个主题的另一个问题是关于计算机系统上存在正在运行的进程的各个位置 - 例如,我有一个程序 C:\Program Files\MyApp\app.exe。当我启动它时,它使用虚拟地址空间加载到进程中,并使用分页(pagefile.sys)来使用有限的 RAM。我的问题是,一旦 app.exe 启动,它是全部加载到 RAM+Pagefile 中还是只从 C:\Program Files\MyApp\myapp.exe 加载程序的一部分,因此它继续引用exe 位置在需要时获取更多信息?

      这取决于系统。在任何设计合理的系统上,都会分配辅助存储来备份进程用户地址空间中的每个有效页面。 “哪里”取决于系统。例如,一些系统使用可执行文件作为代码和静态数据的页面文件。只有可写数据才会进入页面文件。但是,一些原始操作系统不支持以这种方式直接分页到文件。

      最后一个问题 - 在 32 位操作系统上,如果我有超过 4 GB 的 RAM,内存管理可以使用超过 4 GB 的 RAM 空间还是浪费?

      这取决于系统。 32 位操作系统可能使用超过 4GB 的 RAM。每个进程限制为 4GB,但各个进程可以使用超过 4GB 的物理内存。

      假设您有 4K 页面。那12位。理论上,32 位处理器可以有 64 位页表条目。在这种情况下,处理器可以轻松访问超过 4GB 的物理内存。

      更常见的情况是 32 位处理器具有 32 位页表条目。理论上,具有 4K 页的 32 位页表可以访问 2 ^ (32 + 12) 字节的内存。实际上,页表条目中的一些 32 位必须用于系统目的。如果控制位少于 12 个,则处理器可以使用超过 4GB 的物理内存。

      【讨论】:

      • 谢谢。你解开了我的许多疑惑。您的意思是内核永远不应该被视为另一个“进程”,而是一组特权指令,它们映射/存在于每个进程虚拟地址空间(高端)中,并且可以作为运行异常的结果执行在特权模式下。再次感谢。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-02
      • 2018-05-28
      • 1970-01-01
      • 1970-01-01
      • 2020-10-15
      • 2012-09-23
      相关资源
      最近更新 更多