当一个符号需要被加入全局符号表时,如果相同的符号名已经存在。则后加入的符号被忽略
Linux动态链接器,本身是一个共享对象,它的路径是/lib/ld-linux.so.2,这是个软链接,指向/lib/ld-x.y.z.so
这才是真正的动态链接器文件。共享对象也是ELF文件,也是可执行的程序
Windows提供了rundll32.exe的工具,可以把一个dll文件当作可执行文件运行
Linux的ELF动态链接器是Glibc的一部分
符号优先级:当共享模块中多个同名的符号名冲突时,先装入的符号优先,我们把这中优先级方式称为装载序列(load ordering)动态链接器在进行符号的解析以及重定位时,都是采用装载序列。当我们通过dlopen()打开的共享对象进行符号查找时,用一种叫做依赖序列(dependenceordering)的优先级。依赖序列:可以被dlopens打开的那个共享对象为跟节点,对它所有依赖的共享对象进行广度优先遍历,直到找到符号为止。
模块被卸载的过程和装载相反,先执行”.finit”段的代码,然后将相应的符号从符号表中去除,取消进程空间跟模块的映射关系,然后关闭模块文件。
Rundll可以将win下的dll当作程序来运行。Rundll其实就是利用了运行时加载的原理,将指定的对象在运行时加载进来,然后找到某个函数(dll中是dllmain)开始执行
很多高级语言平台如java,。Net里面的反射功能可以实现运行时获得函数的额外信息
Linux共享库的组织
共享库的ABI(二进制接口,applicationbinary interface)跟程序语言有很大的关系。不同语言对接口的兼容性要求不同。ABI对不同的语言来说,主要包括一些诸如函数调用的堆栈结构、符号命名、参数规则、数据结构的内存分布等方面。
Linux规定共享库的文件命名规则如下:libname,so.x.y.z
最前面使用前缀”lib”,中间是库的名字,和后缀”.so”,”y”表示次版本号(minor number),‘z’表示发布版本号(release version number),”x”表示主版本号(major version number)。三个版本号的含义不一样。主版本号表示库的重大升级,不同主版本号的库是不兼容的,次版本号表示库的增量升级,即增加一些新的接口符号,且保持原符号不变,高版本向后兼容低版本。发布版本号表示库的一些错误修正,性能的改进等。并不添加任何新的接口,也不对接口进行更改。
可以说,共享库的主版本号和次版本号决定了一个共享库的接口。
Solaris和linux采用一种叫做so-name的命名机制来记录共享库的依赖关系。这个soname即共享库的文件名去掉次版本号和发布版本号,保留主版本号。“so-name”规定了共享库的接口
在linux中,系统会为每个共享库在它所在的目录创建一个跟”so-name”相同的并且指向它的软连接(symbol link)
软链接可以保证所有以so-name为名的软链接都指向系统中最新版的共享库
建立以so-name为名字的软链接的目的是,使得所有依赖某个共享库的模块,在编译、链接、运行时,都使用共享库的so-name,而不使用详细的版本号
So-name表示一个库的街口,接口不向后兼容,so-name就发送变化,这是最基本的原则
Linux中“ldconfig”,当系统安装或更新一个共享库时,就需要运行这个工具,它会遍历所有默认的共享库目录,如/lib,/usr/lib等,然后更新所有的软链接,使她们指向最新版的共享库;如果安装入新的共享库,那么/ldconfig会为其创建相应的软链接。
大多数包含linux在内的开源操作系统遵守FHS(file hierarchy standard)的标准,这个标准规定了一个系统中的系统文件应该如何存放,包括各个目录的结构、组织和作用,这有利于促进各个开源操作系统间的兼容性。FHS规定,一个系统中主要由三个存放共享库的位置:/lib存放系统最关键和基础的共享库,比如动态链接器,C语言运行库、数学库等,这些库主要是那些/bin和/sbin下的程序所要用到的库,还有系统启动时需要的库
/usr/lib,这个目录下主要保存的是一些非系统运行时所需要的关键性的数据库没,主要是一些开发时用到的共享库,这些共享库一般不会被用户的程序或shell脚本直接用到。这个目录下包含了开发时可能会用到的静态库、目标文件等
./usr/local/lib这个目录用来放置一些跟操作系统并不十分相关的库,主要是一些第三方应用程序的库
总体来看,/lib和/usr/lib是一些很常用的、成熟的,一般是系统本身所需要的库