Linux的地址映射

地址类型

80X86的体系结构,有如下三种地址:

逻辑地址

是虚拟地址空间。就是每个进程使用的独立逻辑地址,通常为4GB。
逻辑地址=段选择符(16bit) + 段内偏移(32bit)。常说的逻辑地址就是这32位段内偏移。

线性地址(虚拟地址)

值从0x00000000到0xffffffff

物理地址

就是物理地址。

映射过程

当进程引用一个逻辑地址时,需完成逻辑地址到物理地址的转换:
逻辑地址–(分段)–>线性地址–(分页)–>物理地址

逻辑地址-(分段)->线性地址

逻辑地址有两部分:段选择符(16bit)+offset(32bit)

段描述符:每个段由一个8字节的段描述符(Segment Descriptor)表示,存放着段首地址、段长度、特权级等信息。

GDT和LDT:全局描述符表GDT,局部描述符表LDT。存放段描述符。

gdtr和ldtr:寄存器。存放GDT和LDT在内存中的地址。

转换过程

  1. 段选择符的TI字段,确定是选gdtr或者ldtr,这就确定了段描述符表的基地址;
  2. 段选择符的index字段,来计算段描述符的地址,即index字段的值乘以8,并将这个结果与GDTR或LDTR寄存器中的内容相加,得到了对应的段描述符表。
  3. offset与段描述符表的Base值相加,得到线性地址。

对于Linux:它只有4个段,而且对应段描述符的Base值均为0.所以offset+base=offset.
得出结论:Linux下,逻辑地址等于线性地址。

线性地址-(分页)->物理地址

32位线性地址=10(页目录)+10(页表)+12(页内偏移)

cr3寄存器:存放正在使用的页目录物理地址。OS进程调度时,自动将当前进程页目录物理地址存入cr3寄存器。

页目录和页表都有1024项(2的10次方)。

缺页异常:如果页目录/页表里的preset标志为0,则将产生缺页异常。将从磁盘把相应页载入内存。

对于Linux:分页过程差不多,只不过Linux使用了多级页目录而已。