一、动态库和静态库的区别
库是一个二进制文件,包含的代码可以被程序调用,如标准库、线程库。Windows 和 Linux下的库文件格式不兼容。
Windows环境:静态库是 .lib 文件,共享库是 .dll 文件
Linux环境:静态库是 .a 文件,共享库是 .so 文件(一般放在 /lib 或者 /usr/lib 目录下)
1、静态库(静态链接)
之所以称为静态库,是因为在链接阶段,把要用到的第三方库的代码加入到目标可执行文件中,这样的话,该可执行文件在运行时就无需去找库文件了。
可执行文件链接静态库的方式,称为静态链接。正是因为如此,这个时候的可执行文件会比较大。
静态库命令规则:以 lib 作为前缀,以 .a作为后缀。如 libxxx.a
优点:程序中已经包含了代码,运行时不需要再加载静态库,运行速度更快
缺点:占用更多的磁盘空间,静态库升级以后,程序需要重新编译链接。
2、动态库(动态链接)
在编译链接时不会把要用到的库文件代码加入到可执行文件中,而是在链接阶段需要用到的时候,去找到对应的库,然后再调用库里的函数。和静态库不同,动态库中保存的是偏移位置,在要用的时候,根据偏移量找到对应的文件。
可执行文件链接动态库的方式,称为动态链接。避免了空间浪费,需要更新库的时候,无需更新执行文件。
动态库:以 lib 作为前缀,以 .so作为后缀。如 libxxx.so
特点:
- 程序不会包含库中代码,尺寸小
- 多个程序可共享一个库
- 库升级方便。无需重新编译程序
Linux中的.so文件 是动态链接的产物
共享库理解为提供各种功能函数的集合,对外提供标准的接口
Linux中命名系统中共享库的规则
主版本号:不同的版本号之间不兼容
次版本号:增量升级 向后兼容
发行版本号:对应次版本的错误修正和性能提升,不影响兼容性
- 在Linux中动态库以
lib
作为前缀, 以.so
作为后缀, 中间是库的名字自己指定即可, 即:libxxx.so
- 在Windows中动态库一般以
lib
作为前缀, 以dll
作为后缀, 中间是库的名字需要自己指定, 即:libxxx.dll
1) 每个动态库有一个包含了真正的库代码的文件名,通常被称为库的 realname ,命名格式通常为 -
libxxx.so.x.y.z,其中so后缀中的x为主版本号,y为副版本号,z为发行版本号。例如,我的linux系统机器上zlib共享库的realname为 libz.so.1.2.8,这个文件是含有可执行的二进制代码的。
2) 每个动态库都有一个以"lib"为前缀且以".so.x"为结尾的被称为 soname
的特定名称,其中x为主版本号,soname命名格式通常为libxxx.so.x。例如,我的linux系统机器上zlib共享库的soname为libz.so.1。这个soname包含了动态库的主版本号,这个doname一般会包含在库代码的头文件中,这个可以使用 readelf -d 读取出来,使用这个动态库的程序的二进制ELF的头文件中包含有这个动态库的soname。程序运行时会按照这个名称去找真正的库文件。
3) 此外,编译链依赖了共享库的应用模块时,链接器只认不带任何版本号的共享库名, 可以将库名称作" linker name。
例如,我的linux系统机器上zlib共享库的linkername为libz.so。也即,链接使用了动态库的程序时查找的动态库名称。例如:gcc -o test test.o -lz , 链接时就会找libz.so 。若没有这个文件,链接器就报错。