根据链接周期的不同,图书馆可以分为静态图书馆和动态图书馆。动态库的链接是在程序执行时链接的。
1 库的分类
根据链接周期的不同,图书馆可以分为静态图书馆和动态图书馆。
静态库是在链接阶段链接的(看起来像废话,但却是事实),所以生成的可执行文件不受库的影响,即使删除了库,程序仍然可以成功运行。
与静态库不同,动态库的链接是在程序执行时链接的。因此,即使程序被编译,库也必须保留在系统中,以便程序在运行时调用。(TODO:链接动态库时,链接阶段到底做了什么)
2 静态库和动态库的比较
其实静态链接库某种意义上是一种粘贴复制,只是它操作的对象是目标代码而不是源代码。因为静态库链接后,库直接嵌入到可执行文件中,带来两个问题。
第一,浪费系统空间。这是显而易见的。试想一下,如果多个程序链接到同一个库,那么每个生成的可执行文件都会有一个库的副本,必然会浪费系统空间。
而且人非圣贤,即使是精心调试的库也难免会出错。一旦在库中发现bug,保存起来比较麻烦。你必须一个一个找出链接到库的程序,重新编译。
动态图书馆的出现正在弥补静态图书馆的上述缺点。因为程序运行时动态库是链接的,所以只需要在磁盘上保留一个副本,这样就节省了磁盘空间。如果发现bug或者很容易升级,就把原来的库换成新的。
那么,静态库没用吗?
回答:不,不,不.不是有句话说:存在即合理吗?既然静态库在历史长河中没有失传,那它一定有它用武之地。想象一下这种情况:如果你用libpcap库编译一个程序要被某人运行,但是他的系统上没有安装pcap库,怎么解决?最简单的方法就是在编译程序的时候把所有要链接的库都链接到它们的静态库,这样你就可以直接在别人的系统上运行程序了。
所谓得与失,因为程序运行时动态库是链接的,所以程序运行速度相对于静态库链接的版本必然要打折扣。但是,缺点并没有隐藏起来。相对于动态库带来的好处,动态库的缺点在今天的硬件上可以忽略不计。因此,链接程序在链接时通常会优先链接动态库,除非使用-static参数来指定链接静态库。
动态链接库
1. 创建动态链接库
复制代码如下:# includes stdio . h void hello(){ printf( hello world/n );}
用命令gcc-sharedhelo.c-o libhello.so编译成动态库.可以看到当前目录下多了一个文件libhello.so。
2. 再编辑一个测试文件test.c,内容如下
复制代码如下:# includes stdio . hint main(){ printf( call hello());hello();}
编译gcc test.c -lhello-l选项告诉编译器使用hello库。奇怪的是动态库的名字是libhello.so,但是这里用的是hello。但这还不够,编译会出错。
在“main”中:test.c: (.text0x1d):对“hello”集合的未定义引用2: LD返回1退出状态这是因为库hello在我们自己的路径中,编译器找不到它。使用-L选项告知hello库gcctest.c-lhello-l.-otest-l的位置,告知编译器在当前目录中查找库文件。
3. 编译成功后执行./test, 仍然出错
找不到图书馆。
有两种方法:
1.您可以将当前路径添加到/etc/ld.so.conf,然后运行ldconfig,或者将当前路径作为参数运行ldconfig(您必须拥有root权限)。
其次,将当前路径添加到环境变量LD_LIBRARY_PATH中。
当然,如果你觉得不会造成混乱,可以直接把库复制到/lib、/usr/lib/等位置(不可避免的,你必须有权限这样做),这样链接器和加载器都能准确找到库。
我们采用第二种方法:
导出LD _ library _ path=。$ LD _ library _ path这样,重新执行就成功了。下面再讲讲静态链接库
还是用之前的hello.c和test.c 1。gcc -c hello.c注意,这里没有使用-shared选项。2.归档目标文件。ar -r libhello.a hello.o程序ar用参数-r创建一个新的库libhello.a,并插入命令行中列出的目标文件。这样,如果库不存在,参数-r将创建一个新的库,如果库存存在,则原来的模块将被新的模块替换。3.在程序中链接静态库gcc test . c-lhello-l .-static-oh hello . static或者gcc test . c lib hello . a-l .-oh hello . static。
生成的hello.static不再依赖于libhello.a.
两个有用的命令
文件程序用于判断文件类型。在文件命令下,所有文件都将被暴露。对了,一招。有时候在windows下用浏览器下载tar.bz2或者tar.bz2文件,后缀会变成一个奇怪的tar.bz2,有些Linux新手不知道怎么解压。但是Linux下的文件类型不受文件后缀的影响,所以我们可以使用命令文件xxx.tar.tar先查看文件类型,然后使用tar和适当的参数对其进行解压缩。
另外也可以通过程序ldd实用程序来判断。Ldd用于打印目标程序链接的所有动态库的信息(由命令行参数指定)。如果目标程序没有链接的动态库,将打印“非动态可执行文件”。关于ldd的用法,请参考联机帮助页。