JavaShuo
《深刻理解linux内核》第二章 内存寻址
时间 2019-11-12
标签
深刻理解linux内核
第二
内存
寻址
个人博客:
www.shishangguan.net
三种不一样的内存地址
逻辑地址(logical address)
包含在linux实际指令中的地址,即分段式地址,是
对应的硬件平台段式管理转换前地址
由16位的段选择符(segment selector)和32位的偏移量组成。
线性地址(linear address)(虚拟地址(virtual address))
是一个32位无符号整数,能够表示4G的地址,值范围从0x00000000-0xffffffff。
线性地址则对应了硬件页式内存的转换前地址。
物理地址(physical address)
用32位或者36位无符号整数表示。用于内存芯片级的单元寻址,与处理器和CPU链接的地址总线相对应。
三者之间的关系
逻辑地址------>
分段单元
------>线性地址------>
分页单元
------>物理地址
硬件中的分段
段选择符和段寄存器
如图所示,16位段选择符的最后13位是索引号,第0和1位是2bit位的请求者特权等级(一共有4中特权等级,linux只使用内核态仍是用户态),第2位为表指示器。
段寄存器有css,ss,ds,es,fs,gs。其中前三个有特殊用途,后三个是通用段寄存器。
段描述符(segment descriptor)
段描述符表放在全卷描述符表(global descriptor table)GDT或者局部描述符表(local descriptor table) LDT 中。
具体的段描述符表类型能够看这里:
http://www.sandpile.org/x86/desc.htm
逻辑地址转线性地址过程
过程分三步:
检查段寄存器中的TI和RPL标志,肯定段描述符在GDT仍是LDT中;
把段寄存器INDEX的值*8+GDT/LDT中保存的地址,便可获得段描述符地址。(该地址在64位处理器是64位,在32位处理器是32位)。
若是咱们用GDB调试程序时,观察几个段寄存器的值,能够和本书及linux源码中的预设值获得印证。段寄存器的INDEX的值正好是在段描述符表中所在的位置。且64位和32位的区别很大。
把逻辑地址的便宜量和段描述符的BASE字段相加便可获得线性地址。
LINUX中的分页
32位系统未开启地址扩展
CR3===>
PGD(10)
==>
PT(10)
==>OFFSET(12) 此时页目录项和页表项是32位的,每一个页表正好在一个页上,恰好是2^10*4Byte=4096kb 恰好是一页。
32位开启物理地址扩展
CR3==>
PGD(2)
==>
PMD(9)
==>
PT(9)
==>OFFSET(12) 此时页目录项和页表项都是64位,但他们是9位的,因此每一个页表占用的恰好是2^9*8Byte 恰好也是一页
64位系统
CR3==>
PGD(9)
==>
PUD(9)
==>
PMD(9)
==>
PT(9)
==>OFFSET(12)
个人博客:
www.while0.com