linux 下库的深入调研

linux操作系统中,linux库文件路径还是比较常用的,于是我研究了一下linux库文件路径,在这里拿出来和大家分享一下,希望对大家有用。

库文件在连接(静态库和共享库)和运行(仅限于使用共享库的程序)时被使用,其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib 和 /usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选其一使用:

1、在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。

2、在 /etc/ld.so.conf 文件中添加库的搜索路径。
  将自己可能存放linux库文件的路径都加入到/etc/ld.so.conf中是明智的选择
  添加方法也极其简单,将库文件的绝对路径直接写进去就OK了,一行一个。例如:
  /usr/X11R6/lib
  /usr/local/lib
  /opt/lib

需要注意的是:第二种搜索路径的设置方式对于程序连接时的库(包括共享库和静态库)的定位已经足够了,但是对于使用了共享库的程序的执行还是不够的。这是因为为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的(ldconfig 命令要以 root 权限执行)。因此,为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行了库搜索路径的设置之后,还必须要运行 /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件之后才可以。ldconfig ,简单的说,它的作用就是将/etc/ld.so.conf列出的路径下的库文件缓存到/etc/ld.so.cache 以供使用。因此当安装完一些linux库文件路径,(例如刚安装好glib),或者修改ld.so.conf增加新的库路径后,需要运行一下 /sbin/ldconfig使所有的库文件都被缓存到ld.so.cache中,如果没做,即使库文件明明就在/usr/lib下的,也是不会被使用的,结果编译过程中抱错,缺少xxx库,去查看发现明明就在那放着,搞的想大骂computer蠢猪一个。

在程序连接时,对于linux库文件(静态库和共享库)的搜索路径,除了上面的设置方式之外,还可以通过 -L 参数显式指定。因为用 -L 设置的路径将被优先搜索,所以在连接的时候通常都会以这种方式直接指定要连接的库的路径。

前面已经说明过了,搜索linux库文件路径的设置有两种方式:在环境变量 LD_LIBRARY_PATH 中设置以及在 /etc/ld.so.conf 文件中设置。其中,第二种设置方式需要 root 权限,以改变 /etc/ld.so.conf 文件并执行 /sbin/ldconfig 命令。而且,当系统重新启动后,所有的基于 GTK2 的程序在运行时都将使用新安装的 GTK+ 库。不幸的是,由于 GTK+ 版本的改变,这有时会给应用程序带来兼容性的问题,造成某些程序运行不正常。为了避免出现上面的这些情况,在 GTK+ 及其依赖库的安装过程中对于库的搜索路径的设置将采用第一种方式进行。这种设置方式不需要 root 权限,设置也简单:
$ export LD_LIBRARY_PATH=/opt/gtk/lib:$LD_LIBRARY_PATH
可以用下面的命令查看 LD_LIBRAY_PATH 的设置内容:
$ echo $LD_LIBRARY_PATH
至此,库的两种设置就完成了。

以上给大家讲解的是linux库文件,关于Linux系统中如何添加自己的库文件路径。

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

下面这篇文章写的非常不错。

经常见有人提起关于库的种种问题,今天我也终于按捺不住,根据自己的经验,实验,学习中得到的一些,来说说自己的一点看法. 
我们都知道库对系统的重要.没了它,系统几乎无法运转,包括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找不到的. 

linux 下库的深入调研

时间: 2024-10-08 20:19:10

linux 下库的深入调研的相关文章

linux下库文件的编程

编程到了一定的时候,总喜欢追求新的东西.将代码尽量模块化就是我的追求之一,原来只是满足于将代码从单文件中分离,通过头文件和实现文件实现模块化,后来发现最好的方法是打包成库文件,使用更加方便.尽管在linux和windows下都有大量的库文件,由于二者的工具不同,加上笔者主要是在linux下编程和教学,因此本文主要介绍Linux下的库文件的制作. 库文件在linux中主要有两种:静态库和动态库(共享库),二者的不同主要有: 1.载入时机不同:静态库是在编译时进行载入到代码中:共享库在运行时载入到代

Linux下库的实现和比较

首先,先创建一个文件夹,我创建的文件夹是shq,以下文件均在此文件夹下.库名为HCY.因为没有好的代码,所以我使用了老师上课的代码. 代码如下: hcy.h add.c div.c mod.c mul.c sub.c testhcy.c makefie 一 没有库的实现 输入命令:make 可执行文件的大小是8696字节 执行可执行文件 二 使用静态库文件,生成静态库.库文件一般以lib为前缀,紧接着是库的名称,扩展名为.a. 可执行文件的大小是958552字节 执行可执行文件 三.使用动态库文

Linux静态库和动态库学习总结

一.废话 之前由于工作需要,要封装一个Linux加密解密转换的动态库,这个之前只做过Windows下面的,Linux下面还真没有做过,之后做了整一个晚上才算做好,不过其中也学到了不少东西,包括Linux下的动态库和静态库,MakeFile等等.之前就已经写了一个练习,之后怕又忘了,总结一下备忘,以后也好查. 很大部分内容都是收集的一些东西还有自己学习的体会,有什么错误或者问题请直接提出. 二.关于库的问题 1.库的原则 现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始.尽量不

Linux&mdash;&mdash;C库

1.库的概念 库是一个二进制文件,包含的代码可被程序调用 标准C库.数学库.线程库-- 库有源码,可下载后编译:也可以直接安装二进制包 /lib /usr/lib 2.库的知识 库是事先编译好的,可以复用的代码. 在OS上运行的程序基本上都要使用库.使用库可以提高开发效率. Windows和Linux下库文件的格式不兼容 Linux下包含静态库和共享库 3.静态库特点 编译(链接)时把静态库中相关代码复制到可执行文件中 程序中已包含代码,运行时不再需要静态库 程序运行时无需加载库,运行速度更快

Linux下Gcc生成和使用静态库和动态库详解

参考文章:http://blog.chinaunix.net/uid-23592843-id-223539.html 一.基本概念 1.1什么是库 在windows平台和linux平台下都大量存在着库. 本质上来说库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主要是编译器.汇编器和连接器的不同),因此二者库的二进制是不兼容的. 本文仅限于介绍linux下的库. 1.2库的种类 linux下的库有两种:静态库和共享库(动态库). 二者的不同

linux下的静态连接库和动态链接库

对linux的静态连接库和动态链接库分不清楚,在看了一篇博文后,现在想做个自己的总结,以加深印象: 1.库的基本概念: 库是可执行代码的二进制形式,其可以被调入操作系统调入内存进行执行. 在window和linux系统,都存在各自的库,但是两种系统的库并不能兼容,因为它们的编译器,连接器,汇编器都是不相同的. 在windows下,静态连接库的后缀是.lib;动态链接库的后缀是.dll 在linux系统下,静态链接库的后缀是.a;动态链接库的后缀是.so 2.静态连接库和动态链接库的命名: 静态连

Linux下 静态链接库 和 动态链接库

先来说说C/C++编译过程 编译: 检查语句符号定义,将C/C++代码翻译生成中间语言. 链接: 将中间代码整合,生成可执行的二进制代码. 简单的说,库文件都是一种特殊的中间语言文件,静态库还是一种特殊格式的归档文件(打包的文件). 使用静态库: 1. 先编写库函数 1 #ifndef _PRINT_TEST_H_ 2 3 #define _PRINT_TEST_H_ 4 #ifdef __cplusplus 5 extern "C" 6 { 7 #endif 8 9 extern i

linux下编译qt5.6.0静态库——configure配置

 随笔 - 116  文章 - 4  评论 - 7 linux下编译qt5.6.0静态库--configure配置 linux下编译qt5.6.0静态库 linux下编译qt5.6.0静态库 configure生成makefile 安装选项 Configure选项 第三方库: 附加选项: QNX/Blackberry选项: Android 选项: 生成makefile 遇到链接检查失败的情况 生成makefile后进行编译 编译时的错误 多重定义'QT_MODBUS()'和'QT_MODBU

【转】Linux下gcc生成和使用静态库和动态库详解

一.基本概念 1.1 什么是库 在Windows平台和Linux平台下都大量存在着库. 本质上来说,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行. 由于windows和linux的平台不同(主要是编译器.汇编器和连接器的不同),因此二者的库的二进制是不兼容的. 本文仅限于介绍linux下的库. 1.2 库的种类 linux下的库有两种:静态库和共享库(动态库). 二者的不同点在于代码被载入的时刻不同. 静态库的代码在编译过程中已经被载入可执行程序,因此体积较大. 共享库的代码是在可