|
知识路径: > 嵌入式系统软件基础知识 > 嵌入式操作系统基础知识 > 存储管理 > 地址重定位(逻辑地址、物理地址、地址映射等) >
|
考试要求:掌握
相关知识点:28个
|
|
|
|
地址映射也叫地址重定位,它涉及到两个基本概念,即物理地址和逻辑地址。
|
|
|
.物理地址也叫内存地址、绝对地址或实地址。也就是说,把系统内存分割成很多个大小相等的存储单元,如字节或字,每个单元给它一个编号,这个编号就称为物理地址。物理地址的集合就称为物理地址空间,或者内存地址空间,它是一个一维的线性空间。例如,假设内存大小为256MB,那么它的内存地址空间是从0x0到0x0FFFFFFF。
|
|
|
.逻辑地址也叫相对地址或虚地址。也就是说,用户的程序经过汇编或编译后形成目标代码,而目标代码通常采用的就是相对地址的形式。其首地址为0,其余指令中的地址都是相对于这个首地址来编址的。
|
|
|
为了保证CPU在执行指令的时候,可以正确地访问内存单元,需要将用户程序中的逻辑地址转换为运行时由机器直接寻址的物理地址,这个过程就称为地址映射。地址映射是由存储管理单元MMU来完成的,如下图所示。
|
|
|
|
|
当一条指令在CPU当中执行时,它可能需要去访问内存,因此就发送一个逻辑地址给MMU,MMU负责把这个逻辑地址转换为相应的物理地址,并根据这个物理地址去访问内存。
|
|
|
下图是一个地址映射的例子。下图(a)是一段简单的C语言程序,首先定义了两个整型变量x和y,然后把x赋值为5,再把x加上3并赋值给y。经过编译链接后,得到的指令形式类似于下图(b)。在它的逻辑地址空间中,首地址为0,代码存放在起始地址为100的地方,数据则放在起始地址为200的地方,第一条指令str 5[200],将常量5保存到地址为200的地方,这条指令对应于源代码中的x=5。也就是说,经过编译和链接后,像x和y这样的符号变量都会被具体的逻辑地址所代替,x的逻辑地址是200,y的逻辑地址是204。接下来的三条指令,对应于源代码中的y=x+3。
|
|
|
|
|
假设这个程序即将开始运行,先要把它装入到内存。如果系统采用的是固定分区的存储管理方法,这个程序将被装入到某个空闲分区当中。假设该分区的起始地址是1000,如上图(c)所示,这是装进去以后的情形。由于程序已经在内存当中,所以现在的地址都是实际的物理地址。但问题立刻就出现了,在程序指令中,它们所采用的地址,还是刚才的逻辑地址,如200、204,但是CPU在执行指令的时候,是按照物理地址来进行的,因此会将200和204当成是内存的物理地址去访问,从而导致出错,因为在物理地址为200和204的地方,存放的很可能是操作系统的内容,如果对这些内容进行读写操作,可能会对操作系统造成破坏,从而引起系统的崩溃。其实这里的本意并非如此,它实际上是想去访问变量x和y,但它们在内存当中的地址是1200和1204,而不是200和204。另外,如果这个程序被装入另外一个分区,起始地址不是1000,那么所有的这些地址又都会发生变化。
|
|
|
因此,为了保证CPU在执行指令时可以正确地访问存储单元,系统在装入一个用户程序后,必须对它进行地址映射,把程序当中的逻辑地址转换为物理地址,然后才能运行。地址映射主要有两种方式:静态地址映射和动态地址映射。
|
|
|
|
静态地址映射的基本思路是:当用户程序被装入内存时,直接对指令代码进行修改,一次性地实现逻辑地址到物理地址的转换。具体实现时,在每一个可执行文件中,要列出各个需要重定位的地址单元的位置,然后由一个加载程序来完成装入及地址转换的过程。这种方式实现起来很简单,不需要任何硬件方面的支持,但它的缺点是,程序一旦装入到内存以后,就不能再移动。
|
|
|
|
|
|
在装入之前,代码内部使用的是逻辑地址。在装入以后,由于分区的起始地址是1000,所以修改这四条指令中的所有逻辑地址,把它们加上起始地址1000,从200变成了1200,从204变成了1204。对于第三条指令,它没有访问任何内存单元,因此就不用去修改它。经过这样的修改后,所有的逻辑地址都转换成了物理地址,因此这一段程序就可以正确地运行了。
|
|
|
|
动态地址映射的基本思路是:当用户程序被装入内存时,不对指令代码做任何的修改。而是在程序的运行过程中,当它需要访问内存单元的时候,再进行地址转换。具体实现时,为了提高效率,该转换工作一般是由硬件的地址映射机制来完成。通常的做法是设置一个基地址寄存器,或者叫重定位寄存器。当一个任务被调度运行时,就把它所在分区的起始地址装入到这个寄存器中。然后,在程序的运行过程中,当需要访问某个内存单元时,硬件就会自动地将其中的逻辑地址加上基地址寄存器当中的内容,从而得到实际的物理地址,并按照这个物理地址去访问。
|
|
|
|
|
|
如上图所示,当程序在装入内存之前,它里面所用的都是逻辑地址。当它被装入内存后,这些指令代码没有发生任何的变化,里面使用的还是逻辑地址。显然,对于这样的程序,如果直接运行的话,肯定会出错。但现在新增加了一个基地址寄存器。有了它以后,指令的执行方式就发生了变化。例如,在执行第三条指令add R2,R1,3时,由于这条指令只涉及到两个CPU寄存器,不需要去访问内存单元,所以它的执行方式和原来是完全一样的,没有任何变化。而对于其他指令,如str 5[200],它需要去访问逻辑地址200。而该地址所对应的变量x,已经存放在物理地址1200的位置。但CPU会自动完成这个转换。当操作系统调度了这个任务去运行时,它所在分区的起始地址,也就是1000,就会被装入到基地址寄存器当中。然后,当执行到str 5[200]这一条指令时,硬件装置就会自动地把其中的相对地址200取出来,把它和基地址寄存器做一个加法,从而得到实际的物理地址,也就是1200,然后再根据这个新的地址来访问内存单元。这样的话,就使得程序能够正确地运行。这个基地址寄存器是位于MMU的内部,整个地址映射过程是自动进行的。从理论上来说,每访问一次内存都要进行一次地址映射。
|
|
|