动态库与静态库_第1页
动态库与静态库_第2页
动态库与静态库_第3页
动态库与静态库_第4页
动态库与静态库_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

动态库与静态库Linux中有两类函数库,分别是静态库和动态库。静态函数库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。动态函数库:这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。linux系统有几个重要的目录存放相应的函数库,如/lib/usr/lib。不管是静态函数库还是动态函数库,都是由*.o目标文件生成。所以先gcc-cstr_out.c静态函数库由ar命令创建本例:ar-crlibstr_out.astr_out.o-c:create的意思-r:replace的意思,表示当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。到此静态函数库创建完毕。使用方法:通过gcc-ooutmain.c-L.-lstr_out编译main.c就会把静态函数库整合进out。其中-L指定静态函数库的位置供查找,注意L后面还有'.’,表示静态函数库在本目录下查找。-1则指定了静态函数库名,由于静态函数库的命名方式是lib***.a,其中的lib和.a忽略。根据静态函数库的特性,此处删除1ibstr_out.a后out依然可以运行,因为静态库的内容已经整合进去了。动态函数库的创建和使用:gcc-shared-fPCI-ooutmain.c-L.-1str_out用该命令生成libstr_out.so动态函数库。gcc-ooutmain.c此时还不能立即./out,因为在动态函数库使用时,会查找/usr/lib/lib目录下的动态函数库,而此时我们生成的库不在里边。这个时候有好几种方法可以让他成功运行:最直接最简单的方法就是把libstr_out.s。拉到/usr/lib或/lib中去。还有一种方法exportLD_LIBRARY_PATH=$(pwd)另外还可以在/etc/ld.so.conf文件里加入我们生成的库的目录,然后/sbin/ldconfig。/etc/ld.so.conf是非常重要的一个目录,里面存放的是链接器和加载器搜索共享库时要检查的目录,默认是从/usr/lib/lib中读取的,所以想要顺利运行,我们也可以把我们库的目录加入到这个文件中并执行/sbin/ldconfig另外还有个文件需要了解/etc/ld.so.cache,里面保存了常用的动态函数库,且会先把他们加载到内存中,因为内存的访问速度远远大于硬盘的访问速度,这样可以提高软件加载动态函数库的速度了。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。程序1:hello.h#ifndefHELLO_H#defineHELLO_Hvoidhello(constchar*name);#endif//HELLO_H程序2:hello.c#include<stdio.h>voidhello(constchar*name)(printf("Hello%s!\n",name);}程序3:main.c#include"hello.h"intmain()(hello("everyone");return0;}无论动态库还是静态库都需要用到.o文件来生成,先编译生成.o文件。gcc-chello.c1:创建静态库静态库文件名的命名规范是以lib为前缀,紧接着跟静态库名,扩展名为.a。例如:我们将创建的静态库名为myhello,则静态库文件名就是libmyhello.a。arcrlibmyhello.ahello.o使用静态库:只需要在你的源程序中加入包含你所需要使用到的函数的声明(即包含头文件),然后在gcc生成目标文件时候指明静态库就OK了(除非你包含的头文件在/usr/include,库文件在标准库/usr/lib,/lib下,否则你得显示指明他们的路径)gcc-ohellomain.c-L.-Imyhello./helloHelloeveryone!删除静态库文件运行./hello,程序正常运行,说明静态库公用函数已经链接到目标文件。2:利用.。文件创建动态库动态库文件扩展名为.so。gcc-shared-fPCI-olibmyhello.sohello.o动态库的使用与静态库使用方式一样gcc-ohellomain.c-L.-lmyhello./hello./hello:errorwhileloadingsharedlibraries:libmyhello.so:cannotopensharedobjectfile:Nosuchfileordirectory哦!出错了。快看看错误提示,原来是找不到动态库文件libmyhello.so。程序在运行时,会在/usr/lib和/lib等目录中查找需要的动态库文件。若找到,则载入动态库,否则将提示类似上述错误而终止程序运行。如何找到生成的动态库有3种方式:1)把库拷贝到/usr/lib和/lib目录下。在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库libhello.so在/home/example/lib目录下:$exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/example/lib修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。当静态库和动态库同名时,gcc命令将优先使用动态库。例如:libhello.solibhello.a为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhello.so.1.0,由于程序连接默认以.so为文件后缀名。所以为了使用这些库,通常使用建立符号连接的方式。ln-slibhello.so.1.0libhello.so.1ln-slibhello.so.1libhello.so1、使用库当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a一个动态库libhello.so,一个头文件hello.h,头文件中提供sayhello()这个函数voidsayhello();另外还有一些说明文档。这一个典型的程序开发包结构与动态库连接linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的sayhello()函数#include<>#include<>intmain()(sayhello();return0;}使用如下命令进行编译$gcc-ctestlib.c-otestlib.o用如下命令连接:$gcctestlib.o-lhello-otestlib连接时要注意,假设libhello.o和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数与与静态库连接麻烦一些,主要是参数问题。还是上面的例子:$gcctestlib.o-otestlib-WI,-Bstatic-lhello注:这个特别的〃-Wl,-Bstatic〃参数,实际上是传给了连接器ld。指示它与静态库连接,如果系统中只有静态库当然就不需要这个参数了。如果要和多个库相连接,而每个库的连接方式不一样,比如上面的程序既要和libhello进行静态连接,又要和libbye进行动态连接,其命令应为:$gcctestlib.o-otestlib-Wl,-Bstatic-lhello-Wl,-Bdynamic-lbye2、动态库的路径问题为了让执行程序顺利找到动态库,有三种方法:把库拷贝到/usr/lib和/lib目录下。在LD_LIBRARY_PATH环境变量中加上库所在路径。例如动态库libhello.so在/home/ting/lib目录下,以bash为例,使用命令:$exportLD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ting/lib修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。3、查看库中的符号有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。库既可以是静态的也可以是动态的。nm列出的符号有很多,常见的有三种:一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的“弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。例如,假设开发者希望知道上文提到的hello库中是否定义了printf():$nmlibhello.so|grepprintfU其中printfU表示符号printf被引用,但是并没有在函数内定义,由此可以推断,要正常使用hello库,必须有其它库支持,再使用ldd命令查看hello依赖于哪些库:$lddhellolibc.so.6=>/lib/libc.so.6(0x400la000)/lib/ld-linux.so.2=>/lib/ld-linux.so.2(0x40000000)从上面的结果可以继续查看printf最终在哪里被定义,有兴趣可以goon4、生成库第一步要把源代码编绎成目标代码。用gcc编绎该文件,在编绎时可以使用任何全法的编绎参数,例如型加入调试代码等:gcc-chello.c-ohello.o连接成静态库连接成静态库使用ar命令,其实ar是archive的意思$arcqslibhello.ahello.o连接成动态库生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:$gcc-shared-Wl,-soname,libhello.so.1-olibhello.so.1.0hello.o另外再建立两个符号连接:$ln-slibhello.so.1.0libhello.so.1$ln-slibhello.so.1libhello.so这样一个libhello的动态连接库就生成了。最重要的是传gcc-shared参数使其生成是动态库而不是普通执行程序。-Wl表示后面的参数也就是-soname,libhello.so.1直接传给连

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论