物理地址,虚拟地址,链接地址的个人理解

时间:2021-11-15 08:49:31

以下仅为个人理解,若有不足之处,望指正。

链接地址,物理地址,虚拟地址这三者地址都有各自的区别,这也是我开发学习过程中,自己琢磨出来领悟的,网上搜索的都讲的很专业化,不太好理解,理解起来感觉有些吃力。所以我想以个人理解的角度,通俗点去讲讲这三者的功能作用。


物理地址

比较简单,就是存储器内(SRAM,SDRAM)分配的真实地址,2440的SRAM前4KB的物理地址是:0x00000000~0x00400000。SDRAM的起始物理地址是0x30000000。
有汇编基础的知道,程序运行流程受PC指针控制,PC指针指向哪个地址,程序就会去这个地址执行
通常情况,没有虚拟地址存在情况,这个PC访问的地址就是物理地址,PC直接指向这个物理地址,在存储器内执行相关代码指令,控制寄存器等动作。


虚拟地址

有时如果程序量过大,存储器内存无法满足程序运行,而内存里某些物理地址是可以被一些不同的程序指令共用,因此为提高内存的利用,采用虚拟内存地址的思想,该虚拟地址容量要大于实际物理地址容量,程序执行时是在虚拟地址上运行,也就是PC指针指向的是虚拟地址。但是虚拟地址运行是控制不了实际存在的物理地址,从而那些寄存器无法被控制。因此需要一个地址映射器(翻译器),将虚拟地址映射到对应的物理地址上(其中多个虚拟地址可对应到同一个物理地址),从而对物理地址进行控制。这个地址映射器叫做“内存管理单元(MMU)”。不是所有芯片都存在这样的单元,而2440内部具有这个单元功能,因此可以采用虚拟地址的思想来运行程序。32位的2440可以建立虚拟内存空间为:0~2^32=0~4GB


链接地址

感觉不是很好理解,我感觉它也一种虚拟存在的地址,但又不完全是。在makefile文件中定义完链接地址后,如:

arm-linux-ld -Ttext 0x3000000 -g -o led_on_elf  crt0.o led_lighton.o

然后执行make进行编译和链接,链接后生成最终的可执行文件led_on_elf ,这个文件第一条指令代码会赋予给它一个链接首地址,就是0x3000000 ,第二条指令后,依次往上。这时程序还没烧录到芯片中,但每条指令都有对应一个链接地址标号,在程序烧录到芯片后,程序仍然是按PC指向的物理或者虚拟地址进行执行(PC首地址为程序烧到芯片里的首地址)。此时链接地址仅是个每条指令的标号,没有产生作用,只有当在指令中直接对PC进行赋值时,如:ldr pc,=main。那么程序就会寻找到main函数对应的地址标号,把这个地址标号,也就是链接地址赋值给PC,此后PC运行的地址就跟着链接地址执行下去,链接地址就等于PC运行地址,链接地址就跟物理(虚拟)地址同步。(或者:ldr pc,=0x30000010,PC就会跳转到链接地址为0x30000010的地方去运行,0x30000010也就成了物理(虚拟)地址)
所以,我觉得把这链接地址叫做代码的地址标号更形象一些。只有当执行对PC赋值时,才能达到位置改变的效果,链接地址就会被读出而产生作用。否则,程序上电,PC还是默认按代码在芯片里的首地址去运行。