一,区别
静态链接是指在链接阶段直接把静态库加入到可执行文件中去,这样可执行文件会比较大。
当程序与静态库连接时,库中目标文件所含的所有将被程序使用的函数的机器码被copy到最终的可执行文件中。这就会导致最终生成的可执行代码量相对变多,相当于编译器将代码补充完整了,这样运行起来相对就快些。不过会有个缺点: 占用磁盘和内存空间. 静态库会被添加到和它连接的每个程序中,而且这些程序运行时, 都会被加载到内存中. 无形中又多消耗了更多的内存空间.
动态链接则是指链接阶段仅仅只加入一些描述信息,而程序执行时再从系统中把相应动态库加载到内存中去。
与共享库连接的可执行文件只包含它需要的函数的引用表,而不是所有的函数代码,只有在程序执行时,那些需要的函数代码才被拷贝到内存中。这样就使可执行文件比较小,节省磁盘空间,更进一步,操作系统使用虚拟内存,使得一份共享库驻留在内存中被多个程序使用,也同时节约了内存。不过由于运行时要去链接库会花费一定的时间,执行速度相对会慢一些,总的来说静态库是牺牲了空间效率,换取了时间效率,共享库是牺牲了时间效率换取了空间效率,没有好与坏的区别,只看具体需要了。
静态链接的大致过程如下图所示:
二,生成
静态链接库:
1、编译生成目标文件
gcc -c struct.c
2、创建静态库(仅仅将编译后的文件进行打包)
ar rcs libstruct.a struct.o (顺序不能乱)
3、链接静态链接库,生成可执行文件
gcc main.c -static-L. -lstruct -o main
(main.c必须放在-lstruct之前)
动态链接库:
1、编译成动态链接库
gcc struct.c -fPIC -shared-o libstruct.so
或者
gcc -c struct.c -o struct.o && gcc -shared -fPCI -o libstruct.so struct.o
(-fpic可以生成小而高效的代码,但是不同的处理器中-fpic生成的GOT(Global Offset Table, 全局偏移表)的大小有限制,另一方面,使用-fPIC的话,任何处理器都可以放心使用。在这里,使用-fPIC。(在X86中使用-fpic和-fPIC 没有任何区别))
2、链接动态链接库,生成可执行文件
gcc main.c -L. -lstruct -o main
3、设置库文件的环境路径
1)在bashrc或profile文件里用LD_LIBRARY_PATH定义,然后用source加载。
2)把库路径添加到ld.so.conf文件中,然后用ldconfig加载。
3)ldconfig /home/user/lib,仅能暂时性使用,若下次ldconfig时此目录下的动态链接库就不能被共享
了。
三,相关命令
nm
功能:
列出编入目标文件或二进制文件的所有符号。用途一:查看程序调用什么函数;用途二:查看一个给定的库或目标文件是否提供了所需的函数。
语法:nm [options] file
常用选项:
-C 将符号名转换为用户级的名字。在让C++函数名可读方面特别有用。
-s 当用于.a文件时,输出把符号名映射到定义该符号的模块或成员名的索引。
-u 只显示未定义的符号,即在被检查的文件外部定义的文件。
-l 使用调试信息输出定义每个符号的行号,或未定义符号的重要位项。
ar
功能:将多个.o文件组合到一起成为.a文件。
语法:ar [options] lib*.a *.o
常用选项:
-c 如果存档文件不存在,则创建,并不显示ar发出的警告。
-q 把*.o添加到存档文件末尾而不检查是否进行替换。
-r 向存档文件中插入.o文件,替换已有的任何同名文件,新成员添加到文档末尾。
-s 创建或升级从符号到.a文件之间的交叉索引映射表,并加入到.a文件中。
等价与ranlib [*.a]。执行该命令后,可用nm –s来查看生成的索引。
-t:显示库的模块表清单。一般只显示模块名。
ldd
功能:显示可执行程序运行所需的共享库。
语法
ldd [options] file
常用选项:
-d 执行重定位并报告所有丢失的函数。
-r 执行对函数和数据对象的重定位并报告丢失的任何函数或数据对象。
四,其它
1. 当Linux静态库和Linux动态库同名时, gcc命令将优先使用动态库。
2. 如果编译的程序是32位的,所需要的动态链接库也需重新编译,例如mplayer需要用到 mp3lame,jpeg-6b,libpng等,均需要重新编译.
3. 如何知道应用程序是64位还是32位的?可使用file命令查看.
staff-1:~# file /bin/ls
4. 在64位的机器上编译32位还是64位程序,主要是要编译器和链接器上加上参数据:-m32 (编译32位) -m64(编译64)