(持续更新)
相关概念
内存地址
当使用80x86(32位)微处理器时,一般分为三种不同的地址:
逻辑地址
包含在机器语言指令中用来指定一个操作数或一条指令的地址。每一个逻辑地址都由一个段(segment)和偏移量(offset或displacement)组成,偏移量指明了从段开始的地方到实际地址之间的距离。
所有段都从0x00000000开始,只需关注段内偏移即可。而段内偏移的值恰好等于线性地址的值。
线性地址(也称虚拟地址)
线性地址通常用十六进制数字表示,值的范围从0x00000000到0xffffffff。
物理地址
用于内存芯片级内存单元寻址。他们与从微处理器的地址引脚发送到内存总线上的电信号相对应。
物理地址
用于内存芯片级内存单元寻址。他们与从微处理器的地址引脚发送到内存总线上的电信号相对应。
地址转换
内存控制单元(MMU)通过一种称为分段单元的硬件电路把一个逻辑地址准换成线性地址;接着,第二个称为分页单元的硬件电路把线性地址转换成一个物理地址。
这个地方有疑问! 逻辑地址一般等于线性地址,那不同的进程中相同的地址是逻辑地址一样?还要继续看。
段选择符
机器语言指令中出现的内存地址,都是逻辑地址。
一个逻辑地址由两部分组成: 段选择符以及偏移量。
段选择符字段
index :指定了放在GDT或LDT中的相对应段描述符的入口。
TI :TI (Table Indicator)标志 :指明段描述符实在GDT(TI=0)中或在LDT中 (TI=1)
RPL :请求者特权级。
段描述符
每个段由一个8字节的段描述符表示,它描述了段的特征。段描述符放在全局描述符表(Global Descriptor Table,GDT)或局部描述符表(Local Descriptor Table, LDT中)。
Linux GDT(全局描述符表)
在单处理器系统中只有一个GDT,而在多处理器系统中每个CPU对应一个GDT。
通常只定义一个GDT,每个进程除了存放在GDT中的段之外如果还需创建附加的段,就有自己的LDT。GDT在主存中的地址和大小存放在gdtr控制寄存器中,当前正被使用的LDT地址和大小放在ldtr控制寄存器中。
段描述符类型
代码段描述符
数据段描述符
任务状态段描述符(TSSD)
局部描述符表描述符(LDTD)
段描述符字段
Base : 包含段的首字节的线性地址
.............
.............
分段单元
逻辑地址转换为线性地址,分段单元执行以下操作
1.通过逻辑地址(由段选择符及偏移量组成)得到段选择符;
2.先检查段选择符的TI字段,判断段选择符保存在哪一个描述符表中。TI字段指明描述符是在GDT中(在这种情况下,分段单元从gdtr寄存器中得到GDT的线性基地址)还是在LDT中(在这种情况下,分段单元从ldtr寄存器中得到LDT的线性基地址);
3.从段选择符的index 字段计算段描述符的地址,index字段的值乘以8(一个段描述符的大小),这个结果与gdtr或ldtr寄存器中的内容相加;
4.把逻辑地址的偏移量与段描述符Base字段的值相加就得到了线性地址。
简单说就是,通过逻辑地址找到段选择符,再找到对应的段描述符,最后得到最后的线性地址。
段描述符中有包含段的首地址的线性地址(base)。