逻辑地址转实体地址?
实体地址是明确的、最终用在总线上的编号。那么怎么转?我为大家介绍的解决方法。希望大家喜欢。
参考如下
1. 实体地址和逻辑地址
实体地址:载入到记忆体地址暂存器中的地址,记忆体单元的真正地址。在前端总线上传输的记忆体地址都是实体记忆体地址,编号从0开始一直到可用实体记忆体的最高阶。这些数字被北桥***Nortbridge chip***对映到实际的记忆体条上。实体地址是明确的、最终用在总线上的编号,不必转换,不必分页,也没有特权级检查***no translation, no paging, no privilege checks***。
逻辑地址:CPU所生成的地址。逻辑地址是内部和程式设计使用的、并不唯一。例如,你在进行C语言指标程式设计中,可以读取指标变数本身值***&操作***,实际上这个值就是逻辑地址,它是相对于你当前程序资料段的地址***偏移地址***,不和绝对实体地址相干。
为什么会有这两种地址?
个人觉的原因在于逻辑地址分配更加灵活,可以允许不唯一,看起来也较为直观,例如,一段程式码中分配阵列,逻辑地址上是连续的,然而在实体地址上,这个阵列所占用的页可能分散开来,实体地址上就是不连续的,这样对程式的可理解性上有影响。另外,有了逻辑地址这个概念,才能使用虚拟记忆体技术。
CPU将一个虚拟记忆体空间中的地址转换为实体地址,需要进行两步:首先将给定一个逻辑地址***其实是段内偏移量,这个一定要理解!!!***,CPU要利用其段式记忆体管理单元,先将为个逻辑地址转换成一个执行绪地址,再利用其页式记忆体管理单元,转换为最终实体地址。
实体地址***physical address***
用于记忆体晶片级的单元定址,与处理器和CPU连线的地址汇流排相对应。
——这个概念应该是这几个概念中最好理解的一个,但是值得一提的是,虽然可以直接把实体地址理解成插在机器上那根记忆体本身,把记忆体看成一个从0位元组一直到最大空量逐位元组的编号的大阵列,然后把这个阵列叫做实体地址,但是事实上,这只是一个硬体提供给软体的抽像,记忆体的定址方式并不是这样。所以,说它是“与地址汇流排相对应”,是更贴切一些,不过抛开对实体记忆体定址方式的考虑,直接把实体地址与物理的记忆体一一对应,也是可以接受的。也许错误的理解更利于形而上的抽像。
虚拟记忆体***virtual memory***
这是对整个记忆体***不要与机器上插那条对上号***的抽像描述。它是相对于实体记忆体来讲的,可以直接理解成“不直实的”,“假的”记忆体,例如,一个0x08000000记忆体地址,它并不对就实体地址上那个大阵列中0x08000000 - 1那个地址元素;
之所以是这样,是因为现代作业系统都提供了一种记忆体管理的抽像,即虚拟记忆体***virtual memory***。程序使用虚拟记忆体中的地址,由作业系统协助相关硬体,把它“转换”成真正的实体地址。这个“转换”,是所有问题讨论的关键。
有了这样的抽像,一个程式,就可以使用比真实实体地址大得多的地址空间。***拆东墙,补西墙,银行也是这样子做的***,甚至多个程序可以使用相同的地址。不奇怪,因为转换后的实体地址并非相同的。
——可以把连线后的程式反编译看一下,发现联结器已经为程式分配了一个地址,例如,要呼叫某个函式A,程式码不是call A,而是call 0x0811111111 ,也就是说,函式A的地址已经被定下来了。没有这样的“转换”,没有虚拟地址的概念,这样做是根本行不通的。
逻辑地址***logical address***
Intel为了相容,将远古时代的段式记忆体管理方式保留了下来。逻辑地址指的是机器语言指令中,用来指定一个运算元或者是一条指令的地址。以上例,我们说的联结器为A分配的0x08111111这个地址就是逻辑地址。
——不过不好意思,这样说,好像又违背了Intel中段式管理中,对逻辑地址要求,“一个逻辑地址,是由一个段识别符号加上一个指定段内相对地址的偏移量,表示为 [段识别符号:段内偏移量],也就是说,上例中那个0x08111111,应该表示为[A的程式码段识别符号: 0x08111111],这样,才完整一些”
线性地址***linear address***或也叫虚拟地址***virtual address***
跟逻辑地址类似,它也是一个不真实的地址,如果逻辑地址是对应的硬体平台段式管理转换前地址的话,那么线性地址则对应了硬体页式记忆体的转换前地址。