linux的内存地址小解

三个比较常见的概念:逻辑地址,线性地址,物理地址。

逻辑地址由段选择符和偏移量组成,段选择符是16位,偏移量是32位。 下面主要讲从逻辑地址到线性地址再到物理地址的转换。

X86中有这么几个段寄存器:cs,ds,ss,es,fs,gs。前三个为专用寄存器,后三个不时专用寄存器。 代码段,数据段,堆栈段。其中段描述符就存放在段寄存器中。

段描述符中前13位index保存段选择符的想对偏移位子。1第14位为0表示使用GDT,为1表示使用LDT。最后两位 描述优先级,一共有四种状态,linux使用了两种,00和11分别表示内核态和用户态。

GDT:全局描述符表,存放段描述符,全局拥有

LDT:局部描述符表,存放段描述符,进程拥有

gdtr寄存器:存放全局描述符表的物理地址。

ldtr寄存器:存放局部描述符表的物理地址。

段描述符由八个字节构成,其中有32为名为base的字段。

段描述符物理地址计算:gdtr or ldtr + index*8

将段描述符中的base字段与逻辑地址的偏移量相加得到的就是线性地址

在上面的过程中我们可以发现,每次要通过逻辑地址获得线性地址都要寻找段描述符的位置,其实在这里,第一次找到段描述符的时候, 会把段描述符加载到一个不可编程的寄存器当中,以后就直接在这个寄存器中取得段描述符就可以了。

从线性地址到物理地址: 在32位系统中,使用了二级页表进行转换,分别为页目录,页表。线性地址被分成10,10,12。

页目录的物理基地址存放在cr3寄存器里面。结合开始的10位,可以找到页目录项。共有1024个页目录项。也目录项中可以找到页表的物理基地址。结合第二个10位, 可以找到页表项。页表项中可以得到页框地址,结合最后12位可以得到具体的物理地址。从这里也可以知道,一个页的大小为4096B.

Xiang Chao 03 May 2012
blog comments powered by Disqus
Fork me on GitHub