内存

内存是用于存放代码和数据地址的硬件,访问速度快,空间大。为高效定位代码和数据的位置,需要建立内存地址,即访问内存空间的索引。一般而言,内存地址有两个:一个是CPU通过总线访问物理内存用到的物理地址,一个是我们编写的应用程序所用到的逻辑地址(也有人称为虚拟地址)。比如如下C代码片段:

  1. int boo=1;
  2. int *foo=&a;

这里的boo是一个整型变量,foo变量是一个指向boo地址的整型指针变量,foo中储存的内容就是boo的逻辑地址。

对于一般的32位CPU而言,以寻址的物理内存地址空间为2\^32=4G字节,支持以页(页大小一般为4KB)为单位对内物理内存空间进行重新编排内存地址,形成虚拟内存地址,而编排虚拟内存地址的策略由操作系统完成。这样操作系统就可以指定不同的物理内存空间给应用程序,而应用程序“看到”的是操作系统在CPU的支持下虚拟化后的地址空间。最终,让操作系统可以更灵活地安排应用程序所占用的内存空间,也简化了应用程序对内存空间的管理。

x86的内存管理

80386是32位的处理器,即可以寻址的物理内存地址空间为2\^32=4G字节。为更好理解面向80386处理器的ucore操作系统,需要用到三个地址空间的概念:物理地址、线性地址和逻辑地址。物理内存地址空间是处理器提交到总线上用于访问计算机系统中的内存和外设的最终地址。一个计算机系统中只有一个物理地址空间。线性地址空间是80386处理器通过段(Segment)机制控制下的形成的地址空间。在操作系统的管理下,每个运行的应用程序有相对独立的一个或多个内存空间段,每个段有各自的起始地址和长度属性,大小不固定,这样可让多个运行的应用程序之间相互隔离,实现对地址空间的保护。

在操作系统完成对80386处理器段机制的初始化和配置(主要是需要操作系统通过特定的指令和操作建立全局描述符表,完成虚拟地址与线性地址的映射关系)后,80386处理器的段管理功能单元负责把虚拟地址转换成线性地址,在没有下面介绍的页机制启动的情况下,这个线性地址就是物理地址。

相对而言,段机制对大量应用程序分散地使用大内存的支持能力较弱。所以Intel公司又加入了页机制,每个页的大小是固定的(一般为4KB),也可完成对内存单元的安全保护,隔离,且可有效支持大量应用程序分散地使用大内存的情况。

在操作系统完成对80386处理器页机制的初始化和配置(主要是需要操作系统通过特定的指令和操作建立页表,完成虚拟地址与线性地址的映射关系)后,应用程序看到的逻辑地址先被处理器中的段管理功能单元转换为线性地址,然后再通过80386处理器中的页管理功能单元把线性地址转换成物理地址。

页机制和段机制有一定程度的功能重复,但Intel公司为了向下兼容等目标,使得这两者一直共存。

上述三种地址的关系如下:

  • 分段机制启动、分页机制未启动:逻辑地址—->段机制处理—->线性地址=物理地址

  • 分段机制和分页机制都启动:逻辑地址—->段机制处理—->线性地址—->页机制处理—->物理地址