当前位置:首页 > 图片 > 国际图片 > 正文
文章正文

linux 动态加载动态库 Linux下动态库和静态库的制作及使用

图片 > 国际图片 > :linux 动态加载动态库 Linux下动态库和静态库的制作及使用是由美文导刊网(www.eorder.net.cn)为您精心收集,如果觉得好,请把这篇文章复制到您的博客或告诉您的朋友,以下是linux 动态加载动态库 Linux下动态库和静态库的制作及使用的正文:

Linux下动态库和静态库的制作及使用

在实际的开发过程中,编写程序往往都需要依赖很多基础的底层库,比方说平时用的较多的标准C库,数学库等等;我们会频繁的使用这些库里的函数,这些函数大多数都是前人为我们写好的,所以值得庆幸的是我们的工作不必从零开始,我们要做的只是在恰当的位置调用合适的库函数去实现相应的功能,充分利用前人的劳动成果,就是“站在巨人的肩膀上”。本文主要简述Linux下库的制作以及使用方法。

一、什么是库

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。根据链接时期的不同,库又有:静态库和共享库(动态库)二者的不同点在于代码被载入的时刻不同。

静态库的代码在编译过程中已经被载入可执行程序,因此体积较大。

共享库的代码是在可执行程序运行时才载入内存的,在编译过程中仅简单的引用,因此代码体积较小。

二、初识静态库与动态库

1.静态函数库

这类库的名字一般是libxxx.a,xxx为库的名字。利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

2.动态函数库

这类库的名字一般是libxxx.M.N.so,同样的xxx为库的名字,M是库的主版本号,N是库的副版本号。当然也可以不要版本号,但名字必须有。相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

三、静态库与动态库的比较

静态库其实从某种意义上来说只不过它操作的对象是目标代码而不是源码而已。因为静态库被链接后库就直接嵌入可执行文件中了,这样就带来了两个问题。

(1)首先就是系统空间被浪费了。这是显而易见的,想象一下,如果多个程序链接了同一个库,则每一个生成的可执行文件就都会有一个库的副本,必然会浪费系统空间。

(2)再者,一旦发现了库中有bug,挽救起来就比较麻烦了。必须一一把链接该库的程序找出来,然后重新编译。

而动态库的出现正弥补了静态库的以上弊端。因为动态库是在程序运行时被链接的,所以磁盘上只须保留一份副本,因此节约了磁盘空间。如果发现了bug或要升级也很简单,只要用新的库把原来的替换掉就行了。

但是静态库也有自己的优点:编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。

四、如何判断一个程序有没有链接动态库

(1)file命令

file程序是用来判断文件类型的,啥文件一看都清楚明了。

(linux 动态加载动态库)

(2)ldd命令

看动态库,如果目标程序没有链接动态库,则打印“not a dynamic executable” (不是动态可执行文件)

五、静态库的制作

(1) 为pr1和pr2生成object文件

gcc -O -c pr1.c pr2.c

(2) ls

(3) 链接静态库

为了在编译程序中正确找到库文件,静态库必须按照 lib[name].a 的规则命名,如下例中[name]=pr.

ar参数意义:

c: create的意思

r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。

s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。

v:该选项用来显示执行操作选项的附加信息。

t:显示库的模块表清单。一般只显示模块名。

ar -crsv libpr.a pr1.o pr2.o

ar -t libpr.a //显示静态库所依赖的文件

(4) 编译链接选项

-L 及-l 参数放在后面.其中,-L 加载库文件路径,-l 指明库文件名字.

gcc -o main main.c -L./ -lpr //生成main

-I后面接头文件 (大写的i)

-L后面接库文件路径路径

-l后面接库文件名,除了“lib”和“.a”部分,全名为libpr.a

(5)执行目标程序

./main

六、动态库的制作

注意,和动态库相关的路径搜索问题可以认为分链接时的搜索 和 运行时加载的搜索。链接时的搜索就是”-L”,比较简单直接,我们重点讲的是运行时的加载搜索。

(1)生成动态库 xxx.so

(linux 动态加载动态库)

gcc -fPIC -Wall -c pr1.c

PIC告诉编译器产生与位置无关代码(Position-Independent Code), 则产生的代码中,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存的任意位置,都可以正确的执行。这正是共享库所要求的,共享库被加载时,在内存的位置不是固定的。

gcc -shared -o libpr.so pr1.o(linux 动态加载动态库)

or use one line:

gcc -O -fPIC -shared -o libpr.so pr1.c

(2)编译时调用动态库

gcc -o test main.c –L. -lpr

采用该方法执行会报告./test: error while loading shared libraries: libpr.so: cannot open shared object file: No such file or directory

原因:因为在动态函数库使用时,会查找/usr/lib、/lib目录下的动态函数库,而此时我们生成的库不在里边。

这个时候有好几种方法可以让他成功运行:(linux 动态加载动态库)

(1)最直接最简单的方法就是把so拉到/usr/lib或/lib中去,但这好像有点污染环境吧。需要root权限,在别人的电脑上会很麻烦;会把系统目录弄得混乱。

(2)新建并编辑/etc/ld.so.conf.d/my.conf文件,加入库所在目录的路径,执行ldconfig命令更新ld.so.cache文件但是需要root权限。

(3)export LD_LIBRARY_PATH=/tmp

不过这样export 只对当前shell有效,当另开一个shell时候,又要重新设置。可以把export LD_LIBRARY_PATH=/tmp 语句写到 ~/.bashrc中,这样就对当前用户有效了,写到/etc/bashrc中就对所有用户有效了。

echo $LD_LIBRARY_PATH

不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。

小结:

总而言之,静态库是以空间换时间,动态库是以时间换空间。无论你是在Linux平台还是Windows平台下做开发,库的使用都大同小异。熟练的使各种库,会给我们带来许多便利,减少工作的负担加快工程的进度,从此升职,加薪不是梦,希望对你有所帮助。

-------------------------------------------------------------

关注 华清远见 微信公众号,与10万个程序员做朋友。

每天下午17:30干货分享,我们不见不散~返回搜狐,查看更多

(linux 动态加载动态库)

一.Linux系统中,我已经写好一个动态库,现在想将一个a.o文件重新加入动态库可以吗?

静态库.a可以,动态库.so不可以。


二.如何让自己的动态链接库文件能够在linux下被调用

  如何让自己的动态链接库文件能够在linux下被调用
  
  VxWorks 安装的DVD有很多自己的动态链接库文件,在启动一些服务的时候需要调用这些动态链接库文件,否则不能启动一些功能,report:找不到相关的库文件。
  
  解决的方法可以有多种:
  
  1. 直接创建软连接的方式,将某动态链接库文件链接到 /lib 或者/usr/lib 下。
  
  ln -s `pwd`/xxx.so /lib/xxx.so
  
  这种方式适合少数固定不变动态链接库文件的调用,但如果文件很多,或者这些文件也是经常存在更新的,这么多比较繁琐。
  
  
  2. 如果直接把动态链接库文件所在的路径直接加到系统查找库的路径下,这里有两种方式:
  
  1) 更改/etc/ld.so.conf, 加入自己的动态链接库路径,好像需要更新/etc/ld.so.cache; 该方法应该可用,没有尝试过。
  
  2) 更改环境变量LD_LIBRARY_PATH,把自己的动态链接库路径,加入到该环境变量中。
  export LD_LIBRARY_PATH=/Jenkins/workspace/Mefa_Nightly_regression_Job02/MAIN/mefa_platform/logs_1st_round/mefaImage&#4尝耽佰甘脂仿拌湿饱溅7;simulatorTools:$LD_LIBRARY_PATH
  在该环境变量中的动态链接库文件会比系统中/lib 或者 /usr/lib 更早调用。
  
  linux重启之后,该环境变量会失效;
  这种方式更适合自动化的测试的需要。


三.如何让linux加载当前目录的动态库

linux 加载当前目录的动态库的方法是:设置合适的环境变量LD_LIBRARY_PATH。
设置方法有以下三种:

1、临时修改,log out之后就失效
在terminal中执行:export LD_LIBRARY_PATH=./

2、让当前帐号以后都优先加载当前目录的动态库
修改~/.bash_profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH

3、让所有帐号从此都优先加载当前目录的动态库
修改/etc/profile在文件末尾加上两行: LD_LIBRARY_PATH=./ 和 export LD_LIBRARY_PATH


四.linux下C/C++动态库在运行时是怎样加载进来的

在linux上,你在ps中说的那种"将动态库作为一个参数传到程序里"的使用方式,是通过dlopen函数将.so加载到当前进程中,并且通过ld.so将.so"链接"进当前进程。这个"链接"过程包括:查找未定义符号在当前进程中的地址、分配数据/代码/bss段内存(数据初始化全局变量、代码段重定位)、执行constructor函数等。之后,可以使用dlsym在已知符号名的情况下通过符号名查找符号对应的地址。这个符号可以是一个全局变量、全局函数等。在你说的C++中,重载的函数也可以理解为全局函数,会有一个属性为weak的符号。该符号的符号名如长绩拜啃之救瓣寻抱默果不做修改,默认按照System V的C++ API命名规范命名(以保证linux下不同编译器编译出来的.so和.o可以通用)。但如果使用extern "C"修饰之后,变成C的函数名,则无名称修饰,便于使用。

它怎样实例化我实现的继承类?
实例化的方式和正常链接一样。例如你在之类Derived中重载了基类Base中函数virtual void foo();那么你需要在你的.so中导出一个可以new Derived()的函数,并且返回结果为Base *,这样别人可以在没有Derived定义的情况下获得运行时类型为Derived的对象。此时别人虽然只有Base *的类型,但是仍然可以和正常链接一样通过虚表查virtual void foo()的地址,从而调用你定义的foo()。
此外,如果你定义了继承类的全局变量,在加载.so的时候该全局变量会自动初始化,你也可以将这个初始化的类通过指向Base *的指针传出去。

如果有大神能解释一下windows下动态库和静态库的原理,小弟感激不尽!
和Linux差不多,不过在实现细节上有些出入。例如windows链接时要直接链接.dll需要通过链接生成这个.dll时生成的.lib,而Linux上直接链接.so即可。不过运行时链接无需这个.lib。静态库都是目标文件的压缩包。都是ELF格式。至于共享内存之类的,仅仅取决于section的属性。


五.Linux下C/C++动态库在运行时是怎样加载进来的

  你说的程序应该是采用了 dynamic loading
  实际上调用了这样一组接口 :
  dlopen dlclose dlsym   函数名被作为参数传递进去,交给动态链接器 ld.so 。随后 ld.so 会在已经加载的动态库中查找与函数名匹配的符号。如果查找成功就可以返回一个地址指向这个窢哗促狙讵缴存斜担铆符号的地址。对于函数,这个地址就相当于是一个函数指针。   而这整个过程可以顺利进行下去,还要依赖于当前程序与动态库的 ABI


六.查看linux当前加载库文件的命令20分

ldd <可执行文件名> 查看可执行文件链接了哪些 系统动态链接库
nm <可执行文件名> 查看可执行文件里面有哪些符号
strip <可执行文件名> 去除符号表可以给可执行文件瘦身
如果我们想从可执行程序里面提取出来一点什么文本信息的话,还可以用strings命令
strings <可执行文件名>

Linux操作系统上面的动态共享库大致分为三类:
1、操作系统级别的共享库和基础的系统工具库
比方说libc.so, libz.so, libpthread.so等等,这些系统库会被放在/lib和/usr/lib目录下面,如果是64位操作系统,还会有/lib64和/usr /lib64目录。如果操作系统带有图形界面,那么还会有/usr/X11R6/lib目录,如果是64位操作系统,还有/usr/X11R6 /lib64目录。此外还可能有其他特定Linux版本的系统库目录。
这些系统库文件的完整和版本的正确,确保了Linux上面各种程序能够正常的运行。
2、应用程序级别的系统共享库
并非操作系统自带,但是可能被很多应用程序所共享的库,一般会被放在/usr/local/lib和/usr/local/lib64这两个目录下面。很多你自行编译安装的程序都会在编译的时候自动把/usr/local/lib加入gcc的-L参数,而在运行的时候自动到/usr/local /lib下面去寻找共享库。
以上两类的动态共享库,应用程序会自动寻找到他们,并不需要你额外的设置和担心。这是为什么呢?因为以上这些目录默认就被加入到动态链接程序的搜索路径里面了。Linux的系统共享库搜索路径定义在/etc/ld.so.conf这个配置文件里面。这个文件的内容格式大致如下:

/usr/X11R6/lib64
/usr/X11R6/lib
/usr/local/lib
/lib64
/lib
/usr/lib64
/usr/lib
/usr/local/lib64
/usr/local/ImageMagick/lib
假设我们自己编译安装的ImageMagick图形库在/usr/local/ImageMagick目录下面,并且希望其他应用程序都可以使用 ImageMagick的动态碃叮百顾知该版双保晶共享库,那么我们只需要把/usr/local/ImageMagick/lib目录加入/etc/ld.so.conf文件里面,然后执行:ldconfig 命令即可。
ldcofig将搜索以上所有的目录,为共享库建立一个缓存文件/etc/ld.so.cache。为了确认ldconfig已经搜索到ImageMagick的库,我们可以用上面介绍的strings命令从ld.so.cache里面抽取文本信息来检查一下:

strings /etc/ld.so.cache | grep ImageMagic......余下全文>>


七.linux动态库和静态库的区别

两者区别:
a,静态库的使用需要:
1 包含一个对应的头文件告知编译器lib文件里面的具体内容
2 设置lib文件允许编译器去查找已经编译好的二进制代码

b,动态库的使用:
程序运行时需要加载动态库,对动态库有依赖性,需要手动加入动态库

c,依赖性:
静态链接表示静态性,在编译链接之后, lib库中需要的资源已经在可执行程序中了, 也就是静态存在,没有依赖性了
动态,就是实时性,在运行的时候载入需要的资源,那么必须在运行的时候提供 需要的 动态库,有依赖性, 运行时候没有找到库就不能运行了

d,区别:
简单讲,静态库就是直接将需要的代码连接进可执行程序;动态库就是在需要调用其中的函数时,根据函数映射表找到该函数然后调入堆栈执行。
做成静态库可执行文件本身比较大,但不必附带动态库
做成动态库可执行文件本身比较小,但需要附带动态库
链接静态库,编译的可执行文件比较大,当然可以用strip命令精简一下(如:strip libtest.a),但还是要比链接动态库的可执行文件大。程序运行时间速度稍微快一点。
静态库是程序运行的时候已经调入内存,不管有没有调用,都会在内存里头。静态库在程序编译时会被连接到目标代码中,程序运行时将不再需要该静态库。
其在编译程序时若链接,程序运行时会在系统指定的路径下搜索,然后导入内存,程序一般执行时间稍微长一点,但编译的可执行文件比较小;动态库是程序运行的时候需要调用的时候才装入内存,不需要的时候是不会装入内存的。
动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入,因此在程序运行时还需要动态库存在。

动态链接库的特点与优势

首先让我们来看一下,把库函数推迟到程序运行时期载入的好处:

1. 可以实现进程之间的资源共享。

什么概念呢?就是说,某个程序的在运行中要调用某个动态链接库函数的时候,操作系统首先会查看所有正在运行的程序,看在内存里是否已有此库函数的拷贝了。如果有,则让其共享那一个拷贝笭互蒂就郦脚垫协叮茅;只有没有才链接载入。这样的模式虽然会带来一些“动态链接”额外的开销,却大大的节省了系统的内存资源。C的标准库就是动态链接库,也就是说系统中所有运行的程序共享着同一个C标准库的代码段。

2. 将一些程序升级变得简单。用户只需要升级动态链接库,而无需重新编译链接其他原有的代码就可以完成整个程序的升级。Windows 就是一个很好的例子。

3. 甚至可以真正坐到链接载入完全由程序员在程序代码中控制。

程序员在编写程序的时候,可以明确的指明什么时候或者什么情况下,链接载入哪个动态链接库函数。你可以有一个相当大的软件,但每次运行的时候,由于不同的操作需求,只有一小部分程序被载入内存。所有的函数本着“有需求才调入”的原则,于是大大节省了系统资源。比如现在的软件通常都能打开若干种不同类型的文件,这些读写操作通常都用动态链接库来实现。在一次运行当中,一般只有一种类型的文件将会被打开。所以直到程序知道文件的类型以后再载入相应的读写函数,而不是一开始就将所有的读写函数都载入,然后才发觉在整个程序中根本没有用到它们。

静态库:在编译的时候加载生成目标文件,在运行时不用加载库,在运行时对库没有依赖性。
动态库:在目标文件运行时加载,手动加载,且对库有依赖性。

具体在开发中用到哪种库,我觉得还是根据实际的内存大小,ROM大小,运行的速度等综合考虑。...余下全文>>


八.linux怎样添加永久动态库环境变量

/etc/ld.so.conf文件里增加动态库所在的路径
或者/etc/l虎旦港秆蕃飞歌时攻江d.so.conf.d下新建.conf文件,内容为加动态库所在的路径

linux 动态加载动态库 Linux下动态库和静态库的制作及使用由美文导刊网(www.eorder.net.cn)收集整理,转载请注明出处!原文地址http://www.eorder.net.cn/pic49154/

文章评论
Copyright © 2006 - 2016 www.eorder.net.cn All Rights Reserved
美文导刊网 版权所有