Linux 共享库文件.docx
- 文档编号:2461574
- 上传时间:2022-10-29
- 格式:DOCX
- 页数:9
- 大小:20.54KB
Linux 共享库文件.docx
《Linux 共享库文件.docx》由会员分享,可在线阅读,更多相关《Linux 共享库文件.docx(9页珍藏版)》请在冰豆网上搜索。
Linux共享库文件
Linux共享库文件
linux共享库文件
(2010-12-1901:
59)
分类:
ubuntu
Linux
支持共享库已经有悠久的历史了,不再是什么新概念了。
大家都知道如何编译、连接以及动态加载(dlopen/dlsym/dlclose)
共享库。
但是,可能很多人,甚至包括一些高手,对共享库相关的一些环境变量认识模糊。
当然,不知道这些环境变量,也可以用共享库,但是,若知道它们,可能
就会用得更好。
下面介绍一些常用的环境变量,希望对家有所帮助:
LD_LIBRARY_PATH
这个环境变量是大家最为熟悉的,它告诉loader:
在哪些目录中可以找到共享库。
可以设置多个搜索目录,这些目录之间用冒号分隔开。
在linux下,还
提供了另外一种方式来完成同样的功能,你可以把这些目录加到/etc/ld.so.conf中,或则在/etc/ld.so.conf.d里创建一个文
件,把目录加到这个文件里。
当然,这是系统范围内全局有效的,而环境变量只对当前shell有效。
按照惯例,除非你用上述方式指明,loader是不会在
当前目录下去找共享库的,正如shell不会在当前目前找可执行文件一样。
LD_PRELOAD
这个环境变量对于程序员来说,也是特别有用的。
它告诉loader:
在解析函数地址时,优先使用LD_PRELOAD里指定的共享库中的函数。
这为调试提
供了方便,比如,对于C/C++程序来说,内存错误最难解决了。
常见的做法就是重载malloc系列函数,但那样做要求重新编译程序,比较麻烦。
使用
LD_PRELOAD机制,就不用重新编译了,把包装函数库编译成共享库,并在LD_PRELOAD加入该共享库的名称,这些包装函数就会自动被调用了。
在linux下,还提供了另外一种方式来完成同样的功能,你可以把要优先加载的共享库的文件名写在/etc/ld.so.preload里。
当然,这是系
统范围内全局有效的,而环境变量只对当前shell有效。
LD_DEBUG这个环境变量比较好玩,有时使用它,可以帮助你查找出一些共享库的疑难杂症(比如同名函数引起的问题)。
同时,利用它,你也可以学到一些共享库加载过程的知识。
它的参数如下:
libsdisplaylibrarysearchpaths
relocdisplayrelocationprocessing
filesdisplayprogressforinputfile
symbolsdisplaysymboltableprocessing
bindingsdisplayinformationaboutsymbolbinding
versionsdisplayversiondependencies
allallpreviousoptionscombined
statisticsdisplayrelocationstatistics
unuseddeterminedunusedDSOs
helpdisplaythishelpmessageandexit
BIND_NOW这个环境变量与dlopen中的flag的意义是一致,只是dlopen中的flag适用于显示加载的情况,而BIND_NOW/BIND_NOT适用于隐式加载。
LD_PROFILE/LD_PROFILE_OUTPUT:
为指定的共享库产生profile数据,LD_PROFILE指定共享库的名称,LD_PROFILE_OUTPUT指定输出profile文件的位置,
是一个目录,且必须存在,默认的目录为/var/tmp/或/var/profile。
通过profile数据,你可以得到一些该共享库中函数的使用统计
信息。
------------------------------------------------------------------------------------------
调用一些别人编写的动态链接库,但是一般都不提供源文件或.lib文件(有些比较抠门的第三方厂商就如此),就无法进行隐式连接隐式连接(默认,无须声明)通过在某些目录搜集共享目标的信息,让系统在程序启动时自动载入和连接共享库显式链接
让程序自己通过库服务(libdl.so)来载入和连接到共享库
makingtheprogramloadandlinkthesharedobjectsthankstosome用3个C++程序来演示这些服务,因为不严格地,C可以认为是C++的子集,出现的问题都是类似的共享的库定义了一个全局的C++类,在载入库时必须进行初始化,在卸载事必须销毁,这套子程序就叫做静态构造和析构器。
共享库还提供了在C语言中的入口(在主程序中被调用),因为C没有mangle(名称修饰)试验1:
用ld建立共享库1)在哪里寻找共享库,虽然LD_LIBRAR_PATH据说是不被推荐使用的
$exportLD_LIBRARY_PATH=${LD_LIBRARY_PATH}:
`pwd`2)建立共享库
$g++-cbase_shared.cc
$ld-sharedbase_shared.o-olibbase_shared.so3)建立主程序
$g++base.cc-L`pwd`-lbase_shared/usr/bin/ld:
a.out:
hiddensymbol`__dso_handle’in/usr/lib/gcc/i486-linux-gnu/4.3.2/crtbegin.oisreferencedbyDSO
/usr/bin/ld:
finallinkfailed:
Nonrepresentablesectiononoutput
collect2:
ldreturned1exitstatus因为引用了一个隐藏的符号__dso_handle,所以报错了我们只好改用下面的共享库创建方式$g++-sharedbase_shared.o-olibbase_shared.so而不是像上面那样用ld,这个很重要然后用下面的选项编译主程序$g++base.cc-L`pwd`-lbase_shared现在可以正常通过了,运行一下$./a.ooutConstructoroftoto
Mainentrypoint
Sharedlibentrypoint,toto’svar=18
Destructoroftoto我们可以看到,主程序动态连接到共享库上了,并且共享库的静态构造和解构器会被自动调用显示链接共享库所谓显示,就是在主程序里面必须声明,Linux下是通过dlopen()来主动打开共享库$g++-cbase_shared.cc
$ld-sharedbase_shared.o-olibbase_shared.so
$g++base1.cc-ldl
$./a.outMainentrypoint
Loadingsharedlib…
./libbase_shared.so:
undefinedsymbol:
__dso_handle运行时报错,因为无法解析__dso_handle我们只好再次选择用gcc生成共享库,并修改编译选项$g++-sharedbase_shared.o-olibbase_shared.so
$g++base1.cc-ldl再试,就好了实际上,我们之需要编译共享库就好了,不需要重新编译主程序,因为主程序的编译是没有问题的,是运行的时候报错可以看到,在调用dlopen的时候,共享库被自动载入了构造过程结论:
无论我们是显式还是隐式调用共享库,要用g++-shared来生成,而不是用ld-shared.因为静态构造器可能会用到If
yoursharedlibrarycontainsglobalorstaticobjectswith
constructors,thenmakesuretousegcc-shared,notld,tocreatethe
sharedlibrary.Thiswillmakesurethatanyprocessor-specificmagic
neededtoexecutetheconstructorsisincluded.gcc/g++链接注意事项-l参数就是用来指定程序要链接的库,-l参数紧接着就是库名
那么库名跟真正的库文件名有什么关系呢?
就拿数学库来说,他的库名是m,他的库文件名是libm.so,很容易看出,把库文件名的头lib和尾.so去掉就是库名了
(用IDA反汇编出,也可以看到库名)-L参数跟着的是库文件所在的目录名。
不然,链接时会找不到库文件,除非你放到标准库目录(/lib,/usr/lib等)PKG_CONFIG_PATH,默认是默认是/usr/lib/pkgconf
pkg-configbase-shared–libs–cflags生成共享库的另外一种方式gcc-sharedtest.c-olibtest.so-fpic使输出的对象模块是按照可重定位地址方式生成的。
(GOT)LIBRART_PATHg++-3.4char.cpp-L.-lsystem-linux-golden-llanguage-linux-golden1)函数要声明为externexternC{}反而不行2)LD_LIBRARY_PATH要设置正确
exportLD_LIBRARY_PATH=.--------------------------------------------------------------------------------------------类似Windows系统中的动态链接库,Linux中也有相应的共享库用以支持代码的复用。
Windows中为*.dll,而Linux中为*.so,我来详细的告诉你如何在linux下编写动态库,以及如何使用它.
在linux下编写动态链接库的步骤:
1.编写库的头文件和源文件.
2.把所有涉及到的源文件用如下方式编译为目标文件:
g++/gcc-g-c-fPIC-olibrary1.olibrary1.cpp
g++/gcc-g-c-fPIC-olibrary2.olibrary2.cpp
......
......
(注释:
-fPIC指通过这个选项来生成与位置无关的代码,可以在任何地址被连接和装载,-c指只编译而不连接原程序)
3.把所有的目标文件链接为动态库:
g++/gcc-g-shared-Wl,-soname,lib***.so-olib***.so.1.0.0library1.olibrary2.o....-lc
(注释:
-lc选项,表示使用c语言库,一般都要用到)
4.建立一个库名链接
ln-slib***.so.1.0.0lib***.so
现在你就可以引用库了.下面我分别给出简单例子告诉你如何动态和静态使用动态库:
假如你的应用程序源代码叫testlib.cpp
采用\如下方式编译:
g++-g-otestlibtestlib.cpp-ldl
(注释:
-ldl选项,表示生成的对象模块需要使用共享库)
////////这
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Linux 共享库文件 共享 文件
![提示](https://static.bdocx.com/images/bang_tan.gif)