可以想象,动态链接模块被装载映射至虚拟空间后,指令部分是在多个进程之间共享的,由于装载时重定位的方法需要修改指令,所以没有办法做到同一份指令被多个进程共享,因为指令被重定位后对于每个进程来讲是不同的。当然,动态连接库中的可修改数据部分对干不同的讲程来说有多个副本,所以它们可以采用装载时重定位的方法来解决。
装载时重定位的一个很大的缺点就是共享对象的指令部分不能被共享,这是不能接受的,有一个简单的解决方案:地址无关码技术
实现的基本想法就是把指令中那些需要被修改的部分分离出来,跟数据部分放在一起,这样指令部分就可以保持不变,而数据部分可以在每个进程中拥有一个副本。
下面是四种模块间的引用方式:
- 第一种是模块内部的函数调用,跳转等
- 第二种是模块内部的数据访问,比如模块中定义的全局变量,静态变量
- 第三种是模块外部的函数调用,跳转等
- 第四种是模块外部的数据访问,比如其他模块中定义的全局变量
第三四种情况:很明显,这些其他模块的全局变量的地址是跟装载地址有关的。ELF的做法是在数据段里面建立一个指向这些变量的指针数组,也被称为全局偏移表。
通过这种方式,以上四种地址引用都实现了地址无关性。
共享模块的法全局变量的处理
ELF共享库在编译时,默认都把定义在模块内部的全局变量当作定义在其他模块的全局变量,也就是说当作前面的类型四,通过GOT来实现变量的访问。当共享模块被装载时,如果某个全局变量在可执行文件中拥有副本,那么动态链接器就会把GOT中的相应地址指向该副本,这样该变量在运行时实际上最终就只有一个实例。如果变量在共享模块中被初始化,那么动态链接器还需要将该初始化值复制到程序主模块中的变量副本:如果该全局变量在程序主模块中没有副本,那么GOT中的相应地址就指向模块内部的该变量副本。
标签:副本,技术,无关,地址,指令,模块,共享,全局变量 From: https://www.cnblogs.com/wuyun--wy/p/17000116.html