装载时重定位(Load Time Relocation)

装载时重定位(Load Time Relocation)

Content #

早在没有虚拟存储概念的情况下,程序是直接被装载进物理内存的。当同时有多个程序运行的时候,操作系统根据当时内存空闲情况,动态分配一块大小合适的物理内存给程序,所以程序被装载的地址是不确定的。系统在装载程序的时候需要对程序的指令和数据中对绝对地址的引用进行重定位。但这种重定位比前面提到过的静态链接中的重定位要简单得多,因为整个程序是按照一个整体被加载的,程序中指令和数据的相对位置是不会改变的。比如一个程序在编译时假设被装载的目标地址为0x1000,但是在装载时操作系统发现0x1000这个地址已经被别的程序使用了,从0x4000开始有一块足够大的空间可以容纳该程序,那么该程序就可以被装载至0x4000,程序指令或数据中的所有绝对引用只要都加上0x3000的偏移量就可以了。

静态链接时的重定位,叫做链接时重定位(Link Time Relocation),而现在这种情况经常被称为装载时重定位(Load Time Relocation),在Windows中,这种装载时重定位又被叫做基址重置(Rebasing)。

装载时重定位无法解决多个进程共享相同指令的问题。动态链接模块被装载映射至虚拟空间后,指令部分是在多个进程之间共享的,由于装载时重定位的方法需要修改指令,所以没有办法做到同一份指令被多个进程共享,因为指令被重定位后对于每个进程来讲是不同的。当然,动态连接库中的可修改数据部分对于不同的进程来说有多个副本,所以它们可以采用装载时重定位的方法来解决。

Linux和GCC支持这种装载时重定位的方法,在产生共享对象时,一般会用到两个 GCC参数“-shared”和“-fPIC”,如果只使用“-shared”,那么输出的共享对象就是使用装载时重定位的方法。

From #

程序员的自我修养