【问题标题】:When do memory addresses get assigned?什么时候分配内存地址?
【发布时间】:2015-01-22 10:00:28
【问题描述】:

考虑以下 CPU 指令,它获取地址 16777386(十进制)的内存并将其存储在寄存器 1 中:

Move &0x010000AA, R1

传统上,程序在编译时被翻译成汇编(机器代码)。 (让我们忽略更复杂的现代系统,如 jitting)。

但是,如果这个地址分配是在编译时静态完成的,那么操作系统如何保证两个进程不使用相同的内存呢? (例如,如果您同时运行相同的编译程序两次)。

问题:

程序如何以及何时分配其内存地址?

虚拟内存:

我了解大多数(如果不是全部)现代系统在硬件中使用内存管理单元以允许使用虚拟内存。地址空间的前几个八位字节用于引用哪个页面。如果每个进程使用不同的页面,这将允许内存保护。但是,如果这是执行内存保护的方式,那么最初的问题仍然存在,只是这次是如何分配页码?

编辑

CPU:

一种可能性是 CPU 可以通过在执行基于内存的指令之前强制由操作系统分配进程 ID 来处理内存保护。然而,这只是推测,需要 CPU 架构的硬件支持,我不确定 RISC ISA 是否会被设计成这样。

【问题讨论】:

    标签: memory memory-management operating-system virtual-memory


    【解决方案1】:

    对于虚拟内存,每个进程都有单独的地址空间,因此一个进程中的 0x010000AA 将引用与另一个进程中不同的值。

    地址空间是通过内核控制的page tables 实现的,处理器用来将虚拟页面地址转换为物理页面地址。让两个进程使用相同的地址页号不是问题,因为这些进程有单独的页表并且映射的物理内存可能不同。

    通常可执行代码和全局变量将被静态映射,堆栈将被映射到随机地址(有些漏洞利用这种方式更难),动态分配例程将使用系统调用来映射更多页面。

    【讨论】:

    • 据我了解,页面查找使用硬件来减少查找的时间成本(是的,内核接管了页面错误,但这应该是异常情况)。那么 MMU 是否跟踪正在运行的进程呢?它怎么知道将 0x010000AA 一次映射到物理地址 X,但稍后将 0x010000AA 映射到物理地址 Y?
    • @James,处理器需要一个指向页表的寄存器(例如 x86 中的 CR3 en.wikipedia.org/wiki/Control_register#CR3 )。
    • 扩展@zch 的注释,每个进程都有自己的页表,因此在上下文切换时,内核将 CR3 寄存器更改为它正在交换的进程的页表基地址。
    【解决方案2】:

    (忽略 Unix fork)进程内存的初始状态由可执行加载程序设置。链接器定义初始内存状态,加载器创建它。该状态通常包括静态数据、可执行代码、可写数据和堆栈的内存。

    在大多数系统中,进程可以通过添加页面(也可能删除它们)来修改地址空间。

    [忽略系统地址] 在虚拟(逻辑)内存系统中,每个进程都有一个从零开始的地址空间(通常第一页没有映射)。地址空间被划分为页面。操作系统将逻辑页面映射(和重新映射)到物理页面。

    一个进程中的地址 0x010000AA 是每个进程中不同的物理内存地址。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-12
      • 2013-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      相关资源
      最近更新 更多