资料程序员Linux 相关文章

三种内存地址

2015-11-09  本文已影响867人  t2othick

三种地址

今天我们来学习一下 Linux 下的内存寻址,通常我们在谈内存地址的时候,我们在谈什么呢?所以首先我们得明确三种地址(以80x86微处理器为例):

以上内容来自 《Understanding The Linux Kernel》

内存管理单元(Memory Management Unit, MMU)通过分段单元的把一个逻辑地址转换成线性地址,通过分页单元把线性地址转换成物理地址。

从 80286 开始,Intel 处理器以两种不同的方式执行地址转换,分别为实模式(real mode)和保护模式(protected mode)。下面我们就展开描述,在保护模式下,硬件的分段机制和分页机制

分段机制

段选择符和段寄存器

逻辑地址有两部分组成:一个段标识符和一个偏移量。短标识符是一个 16 位的字段,成为段选择符;偏移量是一个 32 位长的字段。
为了快速找到段选择符,处理器提供了段寄存器用来存放段选择符,分别为 cs,ss,ds,es,fs,gs。
其中有三个有专门的用途:

段描述符

每个段由一个 8 字节的段描述符表示,描述了段的基本信息。段描述符放在全局描述符表(GDT)或者局部描述符表(LDT)中。
通常只会定义一个 GDT,每个进程除了放在 GDT 中的段以外,如还需要创建附加的段,就可以有自己的 LDT。GDT 在主存中的地址和大小存放在 gdtr 控制寄存器中,LDT 的地址和大小则存放在 ldtr 中。
段描述符包涵以下关键字段:

分段单元

介绍完上述的概念,那么逻辑地址是如何转换到线性地址的呢?我们通过下面的步骤来简单说明:

快速访问分段机制

如果每次都执行上述的过程,可能会比较耗时,因为 GDT 是存储在主存中的,每次都访问主存,可能会比较慢,所以为了提高逻辑地址到线性地址的转换速度,80x86 处理器提供了一组6个不可编程寄存器。每一个不可编程寄存器含有 8 个字节的段描述符,具体的值由相对应的段寄存器中的段描述符确定。每当一个段选择符被装入段寄存器,相对应的段描述符就由主存装入到对应的不可编程寄存器,这样就可以不需要上面三个过程中的前两个,就可以得到线性地址了。

分页机制

页、页框和页表

分页单元把线性地址转换成物理地址,其中的关键任务是把所请求的访问类型与线性地址的访问权限做对比。

常规的分页

从 80386 开始,Intel 处理器的页大小为 4KB。
32 位的线性地址被分为 3 个域:

为什么需要两级呢?目的在于减少每个进程页表所需的 RAM 的数量。如果使用简单的一级页表,将需要高达 2^20 个表项来表示每个进程的页表,即时一个进程并不使用所有的地址,二级模式通过职位进程实际使用的那些虚拟内存区请求页表来减少内存容量。每个活动的进程必须有一个页目录,但是却没有必要马上为所有进程的所有页表都分配 RAM,只有在实际需要一个页表时候才给该页表分配 RAM。

页目录项和页表项的结构如下:

了解了以上结构之后,我们看看如何从线性地址转换到物理地址的:

以上描述的为 80x86 微处理器硬件分页机制,不同架构的 64 位处理器分页机制,大体的思路就是将二级模式拓展为三级(ia64)或者四级(x86_64),以达到对更大范围寻址空间的支持。具体到 Linux 中如何使用操作系统的分段分页机制以及进程的地址空间管理,后续再谈

上一篇 下一篇

猜你喜欢

热点阅读