【问题标题】:Difference between relative and logical address相对地址和逻辑地址之间的区别
【发布时间】:2019-07-04 02:17:20
【问题描述】:

我正在从一本名为《操作系统》的书中阅读有关内存管理的内容。 我之前研究过这个主题并且很清楚,因为只引入了两种类型的地址:物理和逻辑(物理和虚拟)。然而,这本书似乎介绍了三种类型,有时将其中两种视为相同,有时则视为不同。

这是一个引用(我自己翻译的,所以可能不是最好的):

在编写程序时,不知道在哪一点 程序的内存,这就是使用符号地址的原因 (变量名)。将符号地址转换为 物理地址称为地址绑定,它可以在 不同的时间点。如果在编译过程中已知 那么程序将在内存的哪一部分进行地址绑定可以 在那个时候完成。否则(最常见的情况)编译器 生成相对地址(相对于部分的开始 进程获得的内存)。执行程序时 loader 将相对地址映射到物理地址。

这一切似乎都很清楚。相对映射到物理。以下是之后的内容:

在进程执行过程中,与内存的交互是通过 读取和写入内存位置的序列。 CPU要么 从内存中读取指令或数据或将数据写入 记忆。在这两个任务中,CPU 不使用物理 地址,而是 CPU 自己生成的逻辑地址。所有逻辑的集合 地址称为虚拟地址空间。

这已经令人困惑了。逻辑地址和相对地址有什么区别?无论我在哪里查找,它们都不会分开。这是一个更令人困惑的句子:

如果地址绑定在编译时完成并且 加载然后虚拟地址空间匹配物理地址 空间。

前面说过,地址绑定是将符号地址转换为物理地址的过程。但后来才引入相对地址的概念。而加载据说是将相对转换为物理的过程。所以现在我完全迷失在这里了。

假设我们不知道该过程将占用内存的哪一部分:时间线是如何进行的?程序被编译,变量名(符号地址)被翻译成......我猜是相对的?然后CPU需要做一些读/写,它使用......逻辑的?

此外,在本书的以下部分中,相对和逻辑这两个术语似乎是随机使用的。好像它们是相同的,但仍然被定义为不同。

谁能帮我澄清一下?完美的答案可能是程序时间线的人为示例。什么时候引入了哪个地址,逻辑地址和相对地址有什么区别?

提前致谢。

【问题讨论】:

    标签: memory-management operating-system


    【解决方案1】:

    相对地址是指两个位置或地址之间的距离(可以是逻辑的、线性的/虚拟的或物理的,此时并不重要)。

    例如,x86 调用和跳转指令有一种形式,用于指定调用/跳转的距离(从调用/跳转指令结束后的字节开始计数)。该距离被简单地添加到指令指针寄存器 ([R|E]IP) 中,这就是下一条指令将来自的位置(再次,我暂时忽略逻辑,...,物理)。

    如果您的程序包含子程序并使用这样的指令调用它,则程序在内存中的位置无关紧要,因为整体的两个位置之间的距离保持不变(如果整体程序由几个活动部分组成,包括一个或多个库,但我们不要去那里)。

    现在,假设您的程序有一个全局变量并且需要读取它。如果有类似上述调用指令的内存读取指令,可以再次使用指令指针到变量位置的距离。在 64 位 x86 CPU 之前,没有这样的指令/机制来访问数据,只有调用和跳转可以是 IP 相关的。

    在没有这种IP相关的数据寻址机制的情况下,你需要知道变量的实际地址,直到程序被加载到内存中执行时你才知道。在这种情况下所做的是读取变量的指令最初接收变量相对于 IP 的地址(读取变量的指令的地址),或者只是程序的开始。这就是程序存储在磁盘上的方式,指令中包含相对地址。一旦加载,但在程序开始执行之前,读取它的指令中变量的地址会被调整,使其成为实际地址,而不是相对于某些东西(IP 或程序的开始)。程序的起点距离地址 0 越远,需要对该相对地址进行更大的调整。

    明白了吗?

    现在一些几乎完全不同且不相关的东西......

    在 x86 CPU 的上下文中,有以下几种地址:

    • 逻辑
    • 线性/虚拟
    • 物理

    如果我们一直回到 8086/8088... 实际上,如果我们再回到 8080/8085,所有内存地址都是 16 位的,它们不会经过 CPU 的任何转换并按原样呈现到内存中,因此它们是物理的(我们这里不是在谈论 IP/PC 相关的调用/跳转指令)。

    16 位允许 64KB 的内存。 8086/8088 将这 16 位地址扩展为另外 16 位,以寻址超过 64KB 的内存,但它不仅将所有寄存器和地址从 16 位扩大到 32 位。相反,它引入了特殊的段寄存器,它将与 8080/8085 的那些旧的 16 位地址成对使用。因此,一对寄存器,如DS(段寄存器)和BX(常规通用寄存器)可以寻址地址DS * 16 + BX的内存。 DS:BX 是逻辑地址,DS * 16 + BX 是物理地址。通过这个方案,我们可以访问大约 1MB 的内存(只需为两个寄存器插入 65535)。

    80286 稍微改变了上述情况,引入了所谓的保护模式,其中物理地址被计算为segment_table[DS] + BX(这允许从1MB 到16MB),但是这个想法还是一样。

    接下来是 80386,将寄存器扩展到 32 位,并引入了另一层间接。物理地址现在简化了一点,page_tables[segment_table[DS] + EBX]

    DS:EBX 对构成逻辑地址,这是程序操作的(例如在指令MOV EAX, DS:[EBX] 中),这是它可以观察到的。

    segment_table[DS] + EBX 构成线性/虚拟地址(程序可能并不总是知道,因为它无法看到由操作系统管理的表segment_table[])。如果未启用页面转换,则此线性/虚拟地址也等于最终的物理地址。

    启用页面转换后,物理地址page_tables[segment_table[DS] + EBX]

    还有什么要知道的:

    • 逻辑地址可以更复杂,例如DS:[EAX + EBX * 2 + 3]
    • 操作系统通常设置segment_table[] 这样segment_table[any segment register]=0,有效地从图片中删除分割机制并以例如结束。物理地址 = page_tables[EAX + EBX * 2 + 3]。虽然说在这样的设置中逻辑地址和线性/虚拟地址相同 (EAX + EBX * 2 + 3) 并不完全正确,但它确实简化了思考。

    现在,这些段表和页表与开始讨论的相对地址和重定位有什么关系?这些表只是让您将程序放置在物理内存中的任何位置,通常以对程序本身非常透明的方式。它不需要知道它的物理位置或是否启用了页面翻译。

    但是,使用页面翻译有一些好处,但这超出了这里的范围。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-01
      • 2012-04-21
      • 1970-01-01
      • 2019-07-03
      • 2011-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多