Linux-静态链接库和动态链接库

博文说明【前言】:


本文将通过个人口吻介绍Linux中静态链接库和动态链接库相关知识,在目前时间点【2017年6月14号】下,所掌握的技术水平有限,可能会存在不少知识理解不够深入或全面,望大家指出问题共同交流,在后续工作及学习中如发现本文内容与实际情况有所偏差,将会完善该博文内容。

本文参考文献引用链接:

1、http://developer.51cto.com/art/201107/275783.htm【动态链接库】
2、http://www.jianshu.com/p/8743a0edb1ee【好文,讲解动态链接库】
3、http://c.biancheng.net/cpp/html/2750.html【好文,讲解动态链接库】
4、http://www.cnblogs.com/ardar/articles/357321.html【好文,推荐】
5、http://www.cnblogs.com/catch/p/3857964.html【linux下动态链接实现原理】



正文:

写在前面:静态/动态链接库都是库函数的应用,也就是说他们都是库函数。

通常情况下,对函数库的链接是放在编译时期(compile time)完成的。

在使用静态库的情况下, 编译链接可执行文件时,链接器把所有相关的对象文件 (object file)与牵涉到的函数库(library)和应用程序的其他模块组合起来创建最终的可执行文件(.EXE文件)。在运行时,程序与函数库再无瓜葛,因为所有需要的函数已经拷贝进来了下。所以这些函数库被成为静态库(static libaray),换句话说,函数和过程的代码就在程序的可执行文件(exe)中,该文件包含了运行时所需的全部代码,当多个程序都调用相同的函数时,内存中就会存在这个函数的多个拷贝。在Linux中,通常文件名为“libxxx.a”的形式,Windows通常扩展名为.LIB。

当发布产品时,只需要发布这个可执行文件,并不需要发布被使用的静态库。因此,如果有多个程序调用这些函数库,那么在内存中就会存在多个拷贝。

其实,我们也可以将对这些库函数的链接载入推迟到程序运行的时期(runtime)再执行。这就是如雷贯耳的动态链接库(dynamic link library)技术,就是说在程序运行过程中,使用到某个函数时我再调用这些函数,而不是一开始就将所有函数都加载进程序,也就是说动态链接所调用的喊出代码没有被拷贝到程序的可执行文件中去,如果有多个程序调用同一个动态链接库,系统内存中只会有一份数据,在Linux中,通常文件名为“libxxx.so”的形式。

因此目前实际情况是许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当程序真正运行的时候,相应的DLL文件才会被调用。一个应用程序可有多个DLL 文件,同时一个DLL文件也可能被几个应用程序所共用,这样的DLL文件被称为共享DLL文件。

注意:DLL也是一个被编译过的二进制程序,可以被其他程序调用,但与exe不同,DLL不能独立运行必须由其他程序调用载入内存。DLL中封装了很多函数,只要知道函数的入口地址,就可以被其他程序调用。

ps:通过使用 DLL,程序可以实现模块化,程序可以由相对独立的模块组件组成。因为模块是彼此独立的,程序在启动时不用加载所有的模块,因以程序的加载速度更快,而且模块只在相应的功能被请求时才加载。

【示例】:
例如,在 Windows 操作系统中,Comdlg32 DLL执行与对话框有关的常见函数。因此,每个程序都可以使用调用DLL中包含的功能来实现“打开”对话框。这有助于促进代码重用和内存的有效使用。

一、【静态链接库】

1、类库的名字一般是libxxx.a
2、代码的装载速度快,执行速度也比较快,因为编译时它只会把你需要的那部分链接进去。
3、应用程序相对比较大,如果多个应用程序使用的话,会被装载多次,浪费内存。
4、如果静态函数库改变了,那么你的程序必须重新编译。
5、如果你的系统上有多个应用程序都使用该库的话,建议把它编译成动态库,这样虽然刚启动的时候加载比较慢,但是多任务的时候会比较节省内存;如果你的系统上只有一到两个应用使用该库,并且使用的API比较少的话,就编译成静态库吧,一般的静态库还可以进行裁剪编译,这样应用程序可能会比较大,但是启动的速度会大大提高。

二、【动态链接库】

1、类库的名字一般是 libxxx.so
2、共享:多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可;
3、开发模块好:要求设计者对功能划分的比较好。

4、动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。

三、【静态链接库和动态链接库的区别】:

1、简单的说,静态库和应用程序编译在一起,在任何情况下都能运行,而动态库是动态链接,顾名思义就是在应用程序启动的时候才会链接,所以,当用户的系统上没有该动态库时,应用程序就会运行失败。

2、如果程序是在编译时加载库文件的,就是使用了静态库。如果是在运行时加载目标代码,就成为动态库。换句话说,如果是使用静态库,则静态库代码在编译时就拷贝到了程序的代码段,程序的体积会膨胀。如果使用动态库,则程序中只保留库文件的名字和函数名,在运行时去查找库文件和函数体,程序的体积基本变化不大。

3、

静态库的原则是“以空间换时间”,增加程序体积,减少运行时间;

动态库则是“以时间换空间”,增加了运行时间,但减少了程序本身的体积。

4、【案例演示,生成动态链接库文件】:

文件目录树如下:

libtest/
|-- myjob.c
|-- myjob.h
|-- test.c

【静态库部分】

A.做成静态库 libmyjob.a

$ gcc -c myjob.c -o myjob.o 
$ ar -c -r -s libmyjob.a myjob.o

B.链接

$ gcc test.o libmyjob.a -o test

C.引用库情况(无所要信息)

$ ldd test 
linux-gate.so.1 => (0xffffe000) 
libc.so.6 => /lib/libc.so.6 (0xb7e29000) 
/lib/ld-linux.so.2 (0xb7f6e000)

【动态库部分】

A.做成动态库libmyjob.so

$ gcc -Wall –fPIC -c myjob.c -o myjob.o

$ gcc -shared -o libmyjob.so myjob.o

-shared: 该选项指定生成动态连接库(让连接器生成T >类型的导出符号表,有时候也生成弱连接 W >类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件。
-fPIC: 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动>>态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的>。
-L.: 表示要连接的库在当前目录中。
LD_LIBRARY_PATH: 这个环境变量指示动态连接器可以装载动态库的路径。

B.链接
链接方法一、拷贝到系统库里再链接,让 gcc 自己查找:

$ cp libmyjob.so /usr/lib 
$ gcc -o test test.o -lmyjob
这里我们可以看到了 -lmyjob 选项, -l[lib_name] 指定库名,他会主动搜索。 lib[lib_name].so 这个搜索的路径可以通过 gcc --print-search-dirs 来查找。

链接方法二 ,手动指定库路径

$  gcc -o test test.o -lmyjob -B /path/to/lib
-B 选项就添加 /path/to/lib 到 gcc 搜索的路径之中。这样链接没有问题但是方法 II 中手动链接好的程序在 执行 时候仍旧需要指定库路径( 链接和执行是分开的 )。需要添加系统变量 LD_LIBRARY_PATH :

1. $ export LD_LIBRARY_PATH=/path/to/lib 
这个时候再来检测一下test 程序的库链接状况 ( 方法 I 情况 )
   1. $ ldd test 
   2. linux-gate.so.1 => (0xffffe000) 
   3. libmyjob.so => /usr/lib/ libmyjob .so (0xb7f58000) 
   4. libc.so.6 => /lib/libc.so.6 (0xb7e28000) 
   5. /lib/ld-linux.so.2 (0xb7f6f000)
   6. 
是不是比静态链接的程序多了一个 libmyjob.so? 这就是静态与动态的最大区别。

静态情况下,它把库直接加载到程序里,而在动态链接的时候,它只是保留接口,将动态库与程序代码独立。这样就可以提高代码的可复用度,和降低程序的耦合度。
另外,运行时,要保证主程序能找到动态库,所以动态库一般发布到系统目录中,要么就在跟主程序相对很固定的路径里,这样不管主程序在本机何时何地跑,都能找得到动态库。而静态库只作用于链接时,运行主程序后静态库文件没存在意义了。



结尾:

感谢阅读,祝有收获的一天,谢谢!

时间: 2024-10-17 16:07:00

Linux-静态链接库和动态链接库的相关文章

[C] linux静态链接库与动态链接库详解

http://blog.chinaunix.net/u2/76292/showart.php?id=1274181 一顺便说说了哦  通常情况下,对函数库的链接是放在编译时期(compile time)完成的.所有相关的对象文件(object file)与牵涉到的函数库(library)被链接合成一个可执行文件(executable file).程序在运行时,与函数库再无瓜葛,因为所有需要的函数已拷贝到自己门下.所以这些函数库被成为静态库(static libaray),通常文件名为"libxx

linux静态链接库与动态链接库详解

转:http://bbs.chinaunix.net/thread-1281954-1-1.html 二动态链接库的特点与优势  首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:  1.可以实现进程之间的资源共享.   什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了.如果有,则让其共享那一个拷贝:只有没有才链接载入.这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源

Linux下 静态链接库 和 动态链接库

先来说说C/C++编译过程 编译: 检查语句符号定义,将C/C++代码翻译生成中间语言. 链接: 将中间代码整合,生成可执行的二进制代码. 简单的说,库文件都是一种特殊的中间语言文件,静态库还是一种特殊格式的归档文件(打包的文件). 使用静态库: 1. 先编写库函数 1 #ifndef _PRINT_TEST_H_ 2 3 #define _PRINT_TEST_H_ 4 #ifdef __cplusplus 5 extern "C" 6 { 7 #endif 8 9 extern i

Linux 静态链接库和动态连接库

(0)文件夹 VMware 下安装Ubuntu的吐血经历 零基础学习Shell编程 Linux下的makefile的妙用 Linux调试神器 -- gdb 十分钟学会Python的基本类型 Linux 静态链接库和动态连接库 一:静态链接库的应用  三步走~~~ ##g++ -c StaticMath.cpp ##ar -crv libstaticmath.a StaticMath.o ##g++ -o run test_a.cpp -L. -lstaticmath #[@sjs_37_33 l

[C++] 静态链接库和动态链接库的区别

静态链接库和动态链接库的区别 一.静态链接库 预编译->编译->汇编->链接 Linux: 生成目标文件 g++ -c source.cpp -o source.o 打包成静态链接库 ar -crv source.a source.o 使用静态链接库 g++ test.cpp -L静态链接库目录 -l静态链接库名称没有后缀 二.动态链接库 使用动态链接库是为了规避静态链接库的两个问题. 一个是多个副本的问题,对于静态库都是在编译时刻将其编译到源代码当中,在运行时刻不会再和静态库有任何关系

35.静态链接库和动态链接库

35.1.函数库的前世今生 (1)函数库就是一些事先写好的函数的集合,因为函数是模块化的,因此可以被复用:我们写好了某个函数,可以被反复使用,譬如A写好了某个函数然后共享出来,当B有相同的需求时就不需自己写直接用A写好的这个函数即可. (2)最开始是没有函数库的,每个人写程序都要从零开始自己写,时间长了慢慢的早期的程序员就积累下来了一些有用的函数:早期的程序员经常参加行业聚会,在聚会上大家互相交换各自的函数库:后来程序员中的一些大神就提出把大家各自的函数库收拢在一起,然后经过校准和整理,最后形成

静态链接库与动态链接库

静态链接库与动态链接库都是共享代码的方式. 静态链接库(lib): 在程序执行之前完成所有的组装工作,生成一个可执行的目标文件(EXE文件). 静态库的两个特点: 链接后产生的可执行文件包含了所有需要调用的函数的代码,因此占用磁盘空间较大. 如果有多个(调用相同库函数的)进程在内存中同时运行,内存中就存有多份相同的库函数代码,因此占用内存空间较多. 动态链接库(dll&lib): 在程序装载内存的时候才真正的把库函数代码链接进行确定它们的地址,并且就算有几个程序同时运行,内存也只存在一份函数代码

C语言之静态链接库和动态链接库

1:静态链接库 比较早出现的是静态链接库.静态库其实就是商业公司将自己的函数库源代码经过只编译不连接形成.o的目标文件,然后用ar工具将.o文件归档成.a的归档文件(.a的归档文件又叫静态链接库文件).商业公司通过发布.a库文件和.h头文件来提供静态库给客户使用:客户拿到.a和.h文件后,通过.h头文件得知库中的库函数的原型,然后在自己的.c文件中直接调用这些库文件,在连接的时候链接器会去.a文件中拿出被调用的那个函数的编译后的.o二进制代码段链接进去形成最终的可执行程序. 2:动态链接库 动态

静态链接库和动态链接库的区别及优缺点

动态链接库和静态链接库的区别 本文参考了以下博客:      1. http://blog.csdn.net/gamecreating/article/details/5504152      2. http://blog.csdn.net/left_la/article/details/12098545      3. http://blog.csdn.net/augusdi/article/details/6460415 静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序

介绍静态链接库和动态链接库的区别,及在VC++6.0中的建立和使用

首先介绍一下链接库:链接库分为动态链接库和静态链接库两种 LIB是静态链接库,在程序编译连接的时候是静态链接,其对应的文件格式是.lib.即当程序采用静态链接库的时候,.lib文件中的函数被链接到最终的可执行文件中,因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行. DLL是动态链接库,在程序运行的时候被调用,其对应的文件的格式是.dll.即当程序采用动态链接的时候,.dll文件中的函数并没有被链接到可执行文件中,可执行文件只是保存了函数的地址信息.但是