了解动态链接(三)—— 共享模块的全局变量问题

假设 module.c 中引用了一个共享模块中定义的全局变量 global:

1 extern int global;
2
3 int foo() {
4     global = 1;
5 }

编译器无法确定变量 global 的定义是在模块内部还是外部。假设 module.c 是可执行文件的一个源文件,可执行程序不是 PIC 的,不会进行重定位。链接器会在 .bss 段创建一个 global 变量的副本,这样造成同一个变量同时存在于多个位置。问题的解决办法是让所有对变量 global 的访问都指向可执行文件中的那个副本。

ELF 共享库在编译时,默认把所有全局变量都当作是定义在其他模块中,通过 GOT 表实现外部访问。当共享模块被装载时,如果某个全局变量在可执行文件中拥有副本,动态链接器就把 GOT 表中的相应地址指向该副本。如果该变量在可执行文件中没有副本,那么 GOT 表中的相应地址就指向模块内部的该变量副本。

假设 libx.so 中定义了一个全局变量 G,进程A和B都使用 libx.so。那么当 libx.so 被两个进程加载时,它的数据段在每个进程中都有独立的副本,所以进程 A 和 B 访问的都是自己进程中的那个全局变量 G 的副本,相互之间没有影响。但如果是同一个进程的线程 A 和 B,则他们访问的是同一个副本。

而有时希望同一个进程中的不同线程,也访问全局变量的不同副本,这样可以避免线程之间对全局变量的干扰,或者避免做线程同步。这可以通过线程私有存储(Thread Local Storage, TLS) 来实现。在 Android 系统中,TLS是借助协处理器来实现的,在 Linker 和 getpid 等函数的实现中都能看到有关 TLS 的代码。

有时也会希望多个进程共享同一个全局变量的副本,借此实现进程间通信。记得以前写 Windows DLL 时,有“共享数据段”的概念就是实现这个的。

学习资料: 《程序员的自我修养——链接、装载和库》

时间: 2024-10-08 04:49:56

了解动态链接(三)—— 共享模块的全局变量问题的相关文章

动态链接详解

动态链接 动态链接的诞生: 动态链接产生最主要的原因就是静态链接空间浪费过于巨大,更重要的是现阶段各种软件都是模块化开发,不同模块都是由不同厂商开发的,一旦一个模块发生改变,整个软件就需要重新编译(静态链接的情况下). 动态链接主要思想: 把链接这个过程推迟到了运行时再运行,这就是动态链接(Dynamic Linking)的基本思想. 动态链接的好处: 1.动态链接将共享对象放置在内存中,不仅仅节省内存,它还可以减少物理页面的换进换出,也可以提高CPU缓存的命中率,因为不同进程间的数据与指令都集

读《程序员的自我修养 —— 装载与动态链接》乱摘

2016.05.14 – <程序员的自我修养 -- 链接.装载与库>的装载与动态链接部分. - 余甲子 石凡 潘爱民编 个人选读笔记 - 学点表皮. 05.14 PART II 装载与动态链接 1 可执行文件的装载与进程 1.1 进程虚拟地址空间的大小 每个进程拥有自己独立的虚拟地址空间,该虚拟地址空间的大小由计算机的硬件平台决定,具体地说是由CPU的位数决定的(地址线 -- C语言中的指针所占空间).硬件决定了地址空间的最大理论上限,即硬件的寻址空间大小,如32位的硬件平台决定了虚拟地址空间

重学计算机组成原理(九)- 动态链接

把对应的不同文件内的代码段,合并到一起,成为最后的可执行文件 链接的方式,让我们在写代码的时候做到了"复用". 同样的功能代码只要写一次,然后提供给很多不同的程序进行链接就行了. "链接"其实有点儿像我们日常生活中的标准化.模块化生产. 有一个可以生产标准螺帽的生产线,就可生产很多不同的螺帽. 只要需要螺帽,都可以通过链接的方式,去复制一个出来,放到需要的地方 但是,如果我们有很多个程序都要通过装载器装载到内存里面,那里面链接好的同样的功能代码,也都需要再装载一遍,

Linux共享库.so文件的命名和动态链接

Linux中的.so文件 是动态链接的产物 共享库理解为提供各种功能函数的集合,对外提供标准的接口 Linux中命名系统中共享库的规则 主版本号:不同的版本号之间不兼容 次版本号:增量升级 向后兼容 发行版本号:对应次版本的错误修正和性能提升,不影响兼容性 Linux中的共享库并不都是这样的格式 比如GLibc的共享库命名为:libc-x.y.z.so 动态链接器也是GLibc的一部分,使用ld-x.y.z.so命名 libm(数学库)等 SO-NAME机制 系统和程序中要链接的共享库的格式一般

程序的链接和装入及Linux下动态链接的实现

http://www.ibm.com/developerworks/cn/linux/l-dynlink/ 程序的链接和装入及Linux下动态链接的实现 程序的链接和装入存在着多种方法,而如今最为流行的当属动态链接.动态装入方法.本文首先回顾了链接器和装入器的基本工作原理及这一技术的发展历史,然后通过实际的例子剖析了Linux系统下动态链接的实现.了解底层关键技术的实现细节对系统分析和设计人员无疑是必须的,尤其当我们在面对实时系统,需要对程序执行时的时空效率有着精确的度量和把握时,这种知识更显重

实例分析ELF文件动态链接

参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第6章 可执行文件的装载与进程 第7章 动态链接 <Linux GOT与PLT> 开发平台: [[email protected] dynamic_link]# uname -a Linux tanghuimin 2.6.32-358.el6.x86_64 #1 SMP Fri Feb 22 00:31:26 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 实例讲解

[CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口

1 平台 1.1 硬件 Table 1. 硬件(lscpu) Architecture: i686(Intel 80386) Byte Order: Little Endian 1.2 操作系统 Table 2. 操作系统类型 操作系统(cat /proc/version) 位数(uname -a) Linux version 3.2.0-4-686-pae i686(32bit) 1.3 编译器 Table 3. 编译器信息 编译器(gcc -v) gcc (Debian 4.7.2-5) 4

装载与动态链接

装载与动态链接 1可执行文件的装载与进程 可执行文件只有装载到内存后才能被CPU执行.早期的程序装载十分简陋,装载的基本过程就是把程序从外部存储器中读取到内存中的某个位置. 历史有过的装载方式包括覆盖装载.页映射. 1.1 进程虚拟地址空间 程序是一个静态的概念,它就是一些预先编译好的指令和数据集合的一个文件:进程则是一个动态的概念,它是程序运行的一个过程. 每个程序被运行起来以后,都有自己的虚拟地址空间,这个虚拟地址空间的大小由计算机的硬件平台决定,具体地说是由CPU的位数决定的. 1.2 装

计算机科学基础知识(五)动态链接

一.前言 本文以类似hello world这样的简单程序为例,描述了动态连接的概念.第二章描述了整个动态链接的大概过程,随后的两章解析了程序访问动态库中的数据和调用动态库中函数的过程. 注意:阅读本文之前需要先了解relocatable object file.静态链接以及动态库和PIC这些内容. 二.动态链接的过程概述 下面的图展示了动态链接的过程: Static Linker(对于本文的场景,它就是arm-linux-ld)接收下面的输入: (1)命令行参数 (2)linker script