x86体系结构中各种“地址”的概念

之前看CSAPP的时候,看到虚拟地址和物理地址的概念,对CPU的内存映射、地址空间这些有了粗略的印象。后来看了些关于X86的体系结构的内容,感觉相关的概念还是复杂了很多,所以特地整理一下。 (再次证明CSAPP还是当成入门书来看比较合适 ((逃


在具体介绍这些概念之前,还是简单的总结一下X86的实模式和保护模式在内存管理上的区别。

X86的实模式(real mode)始于当年的8086芯片。现在的X86芯片刚启动时也默认先进入实模式。保护模式内存管理比较简单,寻址就是 段地址 + 段内偏移。8086提供了四个16位段寄存器用于保存段地址,分别是CS,DS,ES,SS,段内偏移量也是16位。但是地址线却有20位,也就是说物理地址是20位。所以英特尔公司就设计了一种很巧妙的方法,计算物理地址的时候段基址左移4位,再和偏移地址相加,这就得到了20位的物理地址。

80286处理器首次提出了保护模式的概念,但本文说的保护模式是指IA-32的保护模式。保护模式提供的内存管理机制大概分成了两个部分:分段和分页。分段能够隔离单独的代码模块、数据模块和栈模块,让彼此互不干扰(地址空间分离)。分页提供了虚拟内存的机制,让程序的各个部分能够根据执行环境的需要被映射到物理内存。值得一提的是,分段不能关闭,但是分页是可关闭的。

但是对于几乎所有操作系统来说,其实并没有用到保护模式提供的分段机制。一般都是将所有内存当成一个段来处理,这就是所谓的平坦模式(flat mode)。

物理地址 physical address

物理地址的概念很好理解,就是物理内存真正的地址。CPU最终对于内存的访问就得通过给总线物理地址的信号。

在X86的保护模式下,得到物理地址的方法就是16位的段基址左移4位加上16位的 段内偏移地址,最终得到的就是20位物理地址。

在IA-32的保护模式下,物理地址也是类似的概念,但是扩充到了32位,寻址4GBytes。从Pentium Pro处理器开始,IA-32架构地址扩充到了 2^36 Gbytes。在开启分页的情况下,虚拟地址通过MMU和页表的映射后引发缺页中断或者直接得到物理地址。

有效地址 effective address

有效地址就是段内偏移地址,不论是实模式还是保护模式都是如此。

逻辑地址 logical address

在实模式下,逻辑地址包括16位段地址和16位偏移地址。

在保护模式下,逻辑地址包括16位的段选择子和32位的偏移地址。

至于段选择子是什么,我在英特尔手册上摘抄了一段:

A segment selector is a 16-bit identifier for a segment (see Figure 3-6). It does not point directly to the segment,but instead points to the segment descriptor that defines the segment.

简单来说,段选择子就是一个16位的索引,它不直接指向段,而是指向段描述符。每个段都需要一个段描述符,为了放这些段描述符,在内存中开辟了一些空间,构成一个段描述符表。

也不细讲了,再从手册上摘抄些资料看看凑合吧:

A logical address consists of a segment selector and an offset. The segment selector is a unique identifier for a segment. Among other things it provides an offset into a descriptor table (such as the global descriptor table, GDT) to a data structure called a segment descriptor. Each segment has a segment descriptor, which specifies the size of the segment, the access rights and privilege level for the segment, the segment type, and the location of the first byte of the segment in the linear address space (called the base address of the segment). The offset part of the logical address is added to the base address for the segment to locate a byte within the segment. The base address plus the offset thus forms a linear address in the processor’s linear address space.

线性地址 linear address

在保护模式下,处理器能把每个逻辑地址转换成一个线性地址。线性地址是32位。具体转换方式如下:

  • 通过段选择子中的偏移定位到 GDT 或者 LDT 中的段描述符,读进处理器。
  • 检查段描述符中的各种标志位是否访问本段,然后确认32位的偏移是在段的限制内。
  • 从段描述符中得到段的基址,然后和逻辑地址的32位的偏移相加,就得到了线性地址。

如果没有开启分页,那这个线性地址就已经是物理地址。如果开启了分页,那得到的线性地址就是虚拟地址。

虚拟地址 physical address

从上面对线性地址的描述可以看到,如果开启了分页,那线性地址就是虚拟地址,CPU通过页表的映射可以得到物理地址。