Board logo

标题: 控制共享库的符号可见性-符号可见性简介(1) [打印本页]

作者: look_w    时间: 2018-1-8 15:17     标题: 控制共享库的符号可见性-符号可见性简介(1)

什么是符号和符号可见性符号是谈及对象文件、链接等内容时的基本术语之一。实际上,在 C/C++ 语言中,符号是很多用户定义的变量、函数名称以及一些名称空间、类/结构/名称等的对应实体。例如,当我们定义非静态全局变量或非静态函数时,C/C++ 编译器就会在对象文件中生成符号,这些符号对于链接器(linker)确定不同模块(对象文件、动态共享库、可执行文件)是否会共享相同的数据或代码很有用。            
尽管变量和函数都可能会在模块之间共享,但是对象文件之间的变量共享更为常见。例如,程序员可能会在 a.c 中声明一个变量:
1
extern int shared_var;




却在 b.c 中定义该变量:
1
int shared_var;




这样,两个 shared_var 符号会出现在已编译的对象 a.o 和 b.o 中,最后在链接器解析之后,a.o 中的符号会共享 b.o 的地址。但是,人们很少让变量在共享库和可执行文件之间共享。对于此类模块,通常只会让函数对其他模块可见。有时,我们将此类函数称之为 API,因为我们觉得该模块是为其他模块提供调用的接口。我们也把这种符号称为导出的 (exported),因为它对其他模块可见。注意,此可见性只在动态链接时有效,因为共享库通常在程序运行时被加载为内存映像的一部分。因此,符号可见性 (symbol visibility) 是所有全局符号的一个用于动态链接的属性。
为什么需要控制符号可见性在不同的平台上,XL C/C++ 编译器可能会选择导出或者不导出模块中的所有符号。例如,在 IBM PowerLinux™ 平台上创建 Executable and Linking Format (ELF) 共享库时,默认情况下,所有的符号都会导出。在 POWER 平台上的 AIX 系统中创建 XCOFF 库时,当前 XL C/C++ 编译器在没有工具的帮助下可能会选择不导出任何符号。还有其他方式允许程序员逐个地决定符号可见性(这是本系列下一部分要介绍的内容)。但是,一般不建议导出模块中的所有符号。程序员可以根据需要导出符号。这不仅对库的安全有益,也对动态链接时间有益。
程序员选择导出所有符号时,存在很高的风险,链接时可能会出现符号冲突,尤其是当模块是由不同的开发人员开发的时。因为符号是低级别的概念,所以它不涉及到作用域。只要有人链接一个跟您的库具有相同符号名称的库,当进行链接器解析时,该库就可能会意外地覆盖您自己的符号(但愿会给出一些警告或错误信息)。大多数情况下,此类符号从来不会被从库设计者的角度去使用。因此,为符号创建有限制、有含义(经过深思熟虑)的名称,对于避免此类问题有很大帮助。
对于 C++ 编程,现在越来越注重性能了。然而,由于对其他库的依赖性以及使用特定的 C++ 特性(比如模板),编译器/链接器趋向于会使用和生成大量的符号。因此,导出所有符号会减慢程序速度,并耗用大量内存。导出有限数量的符号可以缩短动态共享库的加载和链接时间。此外,也支持编译器角度的优化,这意味着会生成更有效的代码。
以上关于导出所有符号的缺点解释了为什么一定要定义符号可见性。在本文中,我们将提供一些解决方案来控制动态共享对象 (DSO) 中的符号。用户可以使用不同的方式解决相同的问题,我们将提议特定平台应该首选哪种解决方式。




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0