来自:http://blog.chinaunix.net/u/16651/showart_361289.html
经常见有人提起关于库的种种问题,今天我也终于按捺不住,根据自己的经验,实验,学习中得到的一些,来说说自己的一点看法.
我们都知道库对系统的重要.没了它,系统几乎无法运转,包括LFS整个过程至少是对工具链调整来调整去的过程是以对库的倚赖为核心的.这其中又以动态库为精华.
那先来说简单的静态库.它简单到只是ar打包的目标文件的集合罢了,于是,它的作用也就和目标文件没什么区别了,链接进目标文件,ok,使命完成,至于程序以后的事包括运行则和这个静态库没有关系了.其实我觉的最有说服力的就是例子了,那我们就举最简单的例子.
cat >say.c<<eof
#include "stdio.h"
void say() {
printf("Say!");
}
eof
cat >test.c <<eof
#include "stdio.h"
void say();
main(){
say();
}
eof
gcc -c say.c
ar -r say.a say.o
gcc test.c say.a -o test
ldd test
输出结果让我们看不到任何跟say.a这个我们自己写的静态库的关系.说明程序运行时已经不需要这个静态库了,它已经被ld链接进最终的程序了.
那么动态库,我们继续
gcc -fPIC -shared say.c -o say.so
gcc test.c say.so -o test
ldd test
如果不出意外的话,会出现
say.so => not found.这时的./test是不能运行的.但至少说明程序运行时是需要这个库的.那为什么找不到这个库呢?那就让我们看看系统是怎样寻找这些库的吧.
首先是
ld-linux.so.2这个不能不说,它太重要了,以至于也决定了后面的搜索方式.
先是程序内部决定的.
strings test
还好我们这个test程序不大,不用过滤输出,好,你看见什么,/lib/ld-linux.so.2,say.so,libc.so.6,对,用到的库!
但我们发现不同,有的有路径,有的没有,先不管没有路径的怎么寻找,有路径的肯定是能找到了,那好,我们让say.so也有了路径.
gcc test.c ./say.so -o test2
strings test2
我们发现原来的输出中原来的say.so已经变成了./say.so.运行一下./test2,可以运行了!好,找到库了,这里用的相对路径,无疑,我们 将say.so移动到非当前文件夹.那test就又不能运行了.这样无疑是把我们用到的库硬编码进了程序里.我不喜欢硬编码,太死板.那不硬编码系统怎么找到我们需要的文件呢.
在程序没有把库地址硬编码经进去的前提下,系统会寻找LD_LIBRARY_PATH环境变量中的地址.
LD_LIBRARY_PATH=./ ./test2
如我们所愿,程序正常运行.
如果系统在这一步也没发现我们需要的库呢.
/etc/ld.so.cache这个由ldconfig生成的文件,记载着在/etc/ld.so.conf文件中指明的所有库路径加上/lib,/usr/lib里的所有库的信息.
其实以上这句话只是在大多数情况下是正确的,是否是这个文件由ld-linux.so.2决定.如过你的LFS中的第一遍工具链/tools还在的话,
strings /tools/lib/ld-linux.so.2|grep etc
输出很可能是/tools/etc/ld.so.cache.那么它用的哪个文件我们就清楚了吧.
可这个路径前面的/tools到底和什么有关呢?首先我们可能会想到与ld-linux所在的位置有关.还好我们有3套glib,感谢LFS,现在我们拿第二遍的工具链下手.假设我们的LFS在/lfsroot
strings /lfsroot/lib/ld-linux.so.2
很奇怪的是输出竟然是/etc/ld.so.cache!那这到底和什么有关呢,没错就是我们编译时候的--prefix有关.
现在再看这个/etc/ld.so.conf,和/lib,/usr/lib这些默认ldconfig路径.也都要加上个这个prefix了.
strings /tools/sbin/ldconfig|grep etc
strings /tools/sbin/ldconfig|grep /lib
验证一下吧.
那要是ld.so.cache里也没有记载这个库的地址怎么办呢.
最后在默认路径里找.这个路径一般是/lib,/usr/lib,但也不全是.
strings /tools/lib/ld-linux.so.2|grep /lib
还是要加个prefix.
现在我们反过来思考,不用程序中硬编码的/lib/ld-linux.so.2做动态加载器了.这也可以?!是的!虽然不一定成功.
LD_TRACE_LOADED_OBJECTS=y /tools/lib/ld-linux.so.2 /bin/test
LD_TRACE_LOADED_OBJECTS=y /lib/ld-linux.so.2 /bin/test
LD_TRACE_LOADED_OBJECTS=y /lfsroot/lib/ld-linux.so.2 /bin/test
试着比较结果吧.
不出意外的话第一个是在/tools/lib中搜索的库,二三个都是在/lib中的库.原因我想上面已经说清楚了.
下面以第二个为例说明问题:
LD_LIBRARY_PATH=./ /tools/lib/ld-linux.so.2 ./test
/tools/sbin/ldconfig ./;/tools/lib/ld-linux.so.2 ./test
cp ./say.so /tools/lib/;/tools/lib/ld-linux.so.2 ./test
三种方法应该都会出现我们想要的结果,这里说明/tools/lib/ld-linux.so.2在这里的含义,是用/tools/lib/ld- linux.so.2这个做动态装载器.不信把这个去掉,后两种方法一定不行.因为以./test自己硬编码进去的/lib/ld-linux.so.2 来说,是不会去管/tools/etc/ld.so.cache,和/tools/lib下的库的.
为了说明顺序,我们做如下很危险的实验:
ldconfig /lfsroot/lib;
ldconfig -p
会出现很多内容,但不要试着过滤,因为这时的系统应该很多程序不能运行了.先踏下心来观察.你会发现很多库出现两次/lfsroot/lib,和/lib 而且/lfsroot/lib在前,说明ldconfig先处理参数给出的地址,最后是默认地址.但顺序也不一定,应该还和编译glibc时我们的参数- -enable-kernel有关(我根据种种表现猜测).
加上export LD_LIBRARY_PATH=/lib 环境变量在前面,不能运行的程序又能运行了,说明LD_LIBRARY_PATH变量的优先级优于ld.so.cache
unset LD_LIBRARY_PATH
echo >/etc/ld.so.cache
ldconfig -p
应该什么都不出现,可大部分程序能运行.说明ld-linux.so.2决定的默认路径起了作用(注意,这里的ldconfig的默认路径没有作用)
ldconfig
恢复系统正常.
如果你原意,可以chroot /lfsroot后,再做类似的操作看有什么不同.
懂了原理我们就来应用一下.
拿./test2为例.
我们把它的库给换了!!!
cat >saa.c <<eof
#include "stdio.h"
say(){
printf("I can do something here!!!");
}
eof
gcc -fPIC -shared saa.c -o saa.so
sed "s#\./say\.so#./saa.so#" test >test3
./test3
看看结果吧!
很令人惊奇是么,如果是setuid程序的话...其实这个也很难,因为这种程序我们一般是无法写的(给自己搞破坏不算).这也就明白了为什么长久以来对setuid程序的权限始终如此重视----因为太危险了.
惊奇过后你可能会想,对于未硬编码库地址的程序,我们直接把LD_LIBRARY_PATH改了不也行么?!指向我们的地址,用我们的库,然后...根本不用改什么文件了,要什么写权限了.
呵呵,要真那么容易我们可爱的Linux不也太脆弱了,这恐怕就玩大了,也是你我都不原意见到的.所以,ld-linux.so.2早以作出限止,setsid程序,LD_LIBRARY_PATH变量不起作用.不过文件中的还是有作用的.
最后,说一下ld,和ld-linux.so.2的区别,一个编译时用,一个运行时用,ld负责在它的搜索路径里找到要求的库,并查看是否有提供了需要的 符号(如函数等),如果有,记录相关信息到程序中,由ld-linux.so.2在执行时查找到该库并,并根据相关信息进行需要符号的重定位等工作.注意 这两者的搜索库的方式是不同的.
LC_ALL=C ld --verbose|grep search -i
显示了它默认的查找地址.我们可以做个实验.一般它会有个类似i686-pc-linux-gnu/lib的路径,同时是不在ld-linux.so.2的搜索路径里的.其余的是我们编译是--with-lib-path和LIB_PATH变量指定的.
mv ./say.so XXXX/i686-pc-linux-gnu/lib/libsay.so
gcc -o test4 -lsay test.c
ldd ./test4
结果肯定是libsay.so找不到的.
好了,写到这吧,想起什么再加,有什么不对的地方也望大家多多提出来^^
------------------Skymoon作品,转贴请注明出处作者.
分享到:
相关推荐
本书基于Boost1.42版,介绍了其中的所有99个库,并且详细深入地讲解了其中数十个库,同时实现了若干颇具实用价值的工具类和函数,可帮助读者迅速理解掌握Boost的用法以及应用于实际的开发工作中。 本书内容丰富...
《Boost程序库完全开发指南:深入C++"准"标准库》基于Boost1.42版,介绍了其中所有的99个库,并且详细深入地讲解了其中数十个库,同时实现了若干颇具实用价值的工具类和函数,可帮助读者迅速地理解掌握Boost的用法并...
《深入实践Boost:Boost程序库开发的94个秘笈》是一本专为软件开发者设计的指南,旨在帮助读者深入理解和充分利用Boost库。Boost库是C++编程中的一个强大工具集,它提供了一系列高质量的、经过广泛测试的库,旨在...
这本书——《BOOST程序库完全开发指南》正是面向那些希望深入理解和有效利用BOOST库的开发者们。书中详细阐述了如何利用BOOST库进行高效、可靠的软件开发,涵盖了许多关键的编程概念和技术。 BOOST库包含了各种各样...
STM32 LL库使用指南为开发者提供了关于STM32微控制器(MCU)的低层抽象层(LL)库的详细介绍。LL库是一个寄存器级别的API集合,允许开发者直接对硬件寄存器进行操作,以实现更高的效率。这种库是在STM32Cube库1.1.0...
本书基于Boost1.42版本,对这个版本中的所有99个库进行了详细介绍,其中还对数十个库做了深入讲解。作者还实现了一些实用的工具类和函数,帮助读者更快地掌握Boost的使用方法,并将其应用于实际的软件开发中。 在书...
设计者需要对这些库有深入的理解,以便有效地利用它们来优化设计,提高芯片的性能、功耗和面积(PPA)。通过不断的迭代和优化,设计师可以利用这些强大的工具和库创造出更先进的集成电路,推动电子行业的技术边界。
BOOST程序库完全开发指南:深入C++“准”标准库(第3版).pdf
《深入实践Boost:Boost程序库开发的94个秘笈》一书的英文名为“Boost C++ Application Development Cookbook”,该书从应用角度讲解了实际开发中94个问题如何应用boost来解决,每个都讲了方法、原理及引申的内容...
标题中的“2021最新最全AD封装库3D封装库元件库.zip”指的是一个包含各种封装库、3D模型库以及元件库的压缩文件,适用于Altium Designer(AD)设计软件。这个资源集合了2021年截止时最新的电子设计组件,包括电路板...
《VC++动态链接库(DLL)编程深入浅出》是一本专门为VC++开发者设计的教程,专注于DLL(Dynamic Link Library)编程技术。DLL是Windows操作系统中的一个重要组件,它允许多个程序共享同一段代码和数据,从而节省内存并...
总的来说,处理dll动态链接库和C++依赖库缺失问题需要对系统组件有深入的理解,并且要有耐心和细心去排查每一个可能导致问题的原因。使用专门的修复工具可以简化这个过程,但同时也需要注意工具的来源,确保其安全...
ANSYS Workbench是一款广泛使用的工程仿真软件,它集成了多种分析工具,如结构力学、热力学、流体力学等,为工程师提供了强大...对于经验丰富的用户,深入研究材料库可以进一步优化他们的仿真策略,解决更复杂的问题。
在本文档中,我们将深入探讨STM32F1系列微控制器使用的HAL(硬件抽象层)库。这一系列微控制器是STMicroelectronics(意法半导体)的热门产品,广泛应用于各种嵌入式系统和物联网设备中。HAL库是ST为STM32系列提供的...
本文将深入探讨这些GB零件库的特性、用途以及如何在Solidworks中有效利用。 1. GB零件库的概述 GB零件库是基于中国国家(GB)标准的零部件模型库,包含了大量常见机械部件,如螺栓、螺母、垫圈、轴承、齿轮等。这些...
《C++实现的HTTP协议库——httplib详解...通过深入学习和实践,开发者可以快速掌握HTTP通信的核心技术,并利用httplib库轻松地构建自己的HTTP应用。无论你是新手还是资深程序员,httplib都是一个值得探索和使用的工具。
本文将深入探讨SolidWorks材质库的使用及其在有限元分析中的作用。 首先,我们要理解材质库的重要性。在进行产品设计时,不同的材料具有不同的物理属性,如密度、弹性模量、泊松比等,这些属性直接影响着产品的性能...
它可以读取并处理关于环境气体浓度的数据,比如PM2.5、CO2等,适用于环境监测项目。 9. **Firmata**: Firmata是一个协议,允许Arduino板通过各种编程语言(如 Processing、Java 或 JavaScript)进行远程控制。这个...
这两个工具都有丰富的封装库,其中包含不同电子元件的3D模型和电气特性,以便设计师在设计过程中选择合适的元器件。 Altium Designer是一款集成了电路原理图设计、PCB布局、仿真、制造输出等多环节的综合性设计平台...