首页 > 代码库 > 虚拟地址 线性地址 物理地址 傻傻分不清楚?

虚拟地址 线性地址 物理地址 傻傻分不清楚?

Virtual address  Linear address  Physic address



               


先说说逻辑地址:

           我们时常会看到一种地址的表述方式——segment:offset,比如0x0:0x7c2d

           这里的地址表述方式是逻辑地址方式,在没有开启分段机制之前,物理地址的寻址通过这种方式。

           注意,这种寻址方式非常短暂,一般boot.S里面一旦开启分段了,就不会有这种寻址方式了.

     

          相关的,segment:offset的组织形式,历史上都是称作virtual address,虚拟地址.真正的物理地址是通过

segment<<4 + offset运算得到的. 不管这里的虚拟地址和逻辑地址怎么养,他们的“生存周期”都是非常短的,因为一旦开启分段机制,这种寻址方式就被替代了. 面向应用的程序员几乎很少接触到这类地址(注意一点是造成混淆的重要原因之一)


线性地址:

分段机制开启之后就是使用的线性地址了

比方说下面截图中,那个mov 0x1001c %eax 就是使用的线性地址,<bootmain>旁边的那个00007d0a也是地址,线性地址,当前obj文件代码段内的地址


             上述这个反汇编看到的截图地址和我们平日写hello world反汇编看到的地址无异,都是使用的线性地址。而由于普通的user space用户一般都不会去接触boot.S那段代码。所以根本就没有逻辑地址的“需求”.对于普通用户来说,就两种地址,要么这个地址是"假的" ,要么这个地址是“真的”,这里理解的假,真,都是由于对是否这个地址真正对应物理内存来说的。由于用户空间的线性地址不是真正对应的物理地址,所以人们就把这种地址叫做虚拟地址


所才会有下图(截取自CSAPP)的现象,明明是线性地址空间,被称作虚拟内存.


自然的物理内存地址就不必说了.           



之所以这么强调地址概念的区分.一是之前自己晕了好久,半吊子,似懂非懂.

再者,遇到一个问题,触发我去把这个理清楚

看下面的截图,这段代码出自Xv6(MIT-JOS)的 /kern/pmap.h

第一个函数的功能说明是把“takes a kernel virtual address,returns the corresponding physical address”

这里说的把把虚拟地址转换成物理地址就是把线性地址转换成物理地址,

而且实现方法也论证了这一点, 直接的kva - KERNBASE ,这里KERNBASE是0xF0000000

而这里指的“物理地址”也不是别的IO端口的地址,就是内存地址,内存的首地址被映射到KERNBASE

So ...现在就很清楚了


第二个把物理内存地址转换成线性地址就是直接把physical address加上 KERNBASE即可 : -)



总结:

          人们会容易混淆的原因在于直接把线性地址称作虚拟地址了,这并没有错(听线性地址的人也不多吧),对于大多数程序员来说,都是接触的线性地址,由于这个地址不是实际的物理地址,所以就习惯性的称作虚拟地址了.使用范围内也就是这个“虚拟地址”(比方说写个C hello world,里面反汇编也就看到的是线性地址)。 大多数人不需要接触到真正的物理地址,这里的概念就变成了对比性的了,不是物理地址的就是虚拟的,使用的是线性地址,由于"不需要那么多概念",于是就把虚拟地址和线性地址挂钩了,而且这里早期的分段未开启的时候虚拟地址的概念已经不存在了,这样时候不会有重叠,于是大家都这么用了....



仅此个人学习总结,如有误解望及时指正.



虚拟地址 线性地址 物理地址 傻傻分不清楚?