ldd ldconfig LD_LIBRARY_PATH LIBRARY_PATH 动态链接库
ldd ldconfig LD_LIBRARY_PATH LIBRARY_PATH 动态链接库
201208 Chenxin
20140607 update Chenxin
1./etc/profile LD_LIBRARY_PATH=/usr/local/mysql/lib:/usr/local/glibc-2.14/lib (优先级最高)
2./lib64系统默认的/lib64和/usr/lib64(前者应该是高于后者).
3./etc/ld.so.conf之后要执行一遍ldconfig刷新一下cache才行(/etc/ld.so.cache)
以上通过自己试验得到.(之所以3在2之后,可能是怕误修改后造成系统无法启动)
要查看 ldconfig 可以“看到”的所有共享库,请输入:
ldconfig -p | less
strings /usr/lib/libstdc++.so.6 | grep GLIBC #strings命令用于查看二进制文件里的文本内容,尽可能的显示出来.
ldconfig -p |grep "libc.so."
strings /usr/local/glibc-2.14/lib/libc.so.6 |grep "GLIB"
- 向/lib64,/usr/lib64里加东西( 系统默认就会ldconfig这两个目录下的库 ).是不用修改/etc/ld.so.conf的,但是完了之后要调一下ldconfig刷新,不然这个library会找不到.
- 向其他目录加东西,要修改/etc/ld.so.conf,然后再调用ldconfig刷新,不然会找不到.( 也可以修改LD_LIBRARY_PATH指向,其优先级最高.或者修改/etc/ld.so.conf,优先级比较低 )
cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
/usr/local/mysql/lib
执行ldconfig,再执行ldconfig -p将所有库文件信息打印出来检查
ldconfig -p |grep mysql (貌似加在LD_LIBRARY_PATH里的,ldconfig -p没有显示出来)
libmysqlclient_r.so.16 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient_r.so.16
libmysqlclient.so.18 (libc6,x86-64) => /usr/local/mysql/lib/libmysqlclient.so.18
libmysqlclient.so.16 (libc6,x86-64) => /usr/lib64/mysql/libmysqlclient.so.16
libmysqlclient.so (libc6,x86-64) => /usr/local/mysql/lib/libmysqlclient.so - 如果想在其他目录放lib,但是又不想在/etc/ld.so.conf中加东西(或者是没有权限加东西),只能通过LD_LIBRARY_PATH.
就是export一个全局变量LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找library.(但其优先级是最高的). - ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是该加-L就得加,不要混淆了。
LD_LIBRARY_PATH LIBRARY_PATH说明
20140607
Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径。(LD_LIBRARY_PATH 变量指定的路径在默认路径之前查找)
执行函数动态链接.so时,如果此文件不在缺省目录下‘/lib’ and ‘/usr/lib’.
那么就需要指定环境变量LD_LIBRARY_PATH
假如现在需要在已有的环境变量上添加新的路径名,则采用如下方式:
LD_LIBRARY_PATH=NEWDIRS:$LD_LIBRARY_PATH.(newdirs是新的路径串)
注:GNU系统可以自动添加在 /etc/ld.so.conf文件中来实现环境变量的设置
LD_LIBRARY_PATH这个环境变量是大家最为熟悉的,它告诉loader:在哪些目录中可以找到共享库。可以设置多个搜索目录,这些目录之间用冒号分隔开。
在linux下,还提供了另外一种方式来完成同样的功能,你可以把这些目录加到/etc/ld.so.conf中,或则在/etc/ld.so.conf.d里创建一个文件,把目录加到这个文件里。
当然,这是系统范围内全局有效的(ld.so.conf方式), 而环境变量只对当前shell有效(LD_LIBRARY_PATH)。
按照惯例,除非你用上述方式指明,loader是不会在当前目录下去找共享库的,正如shell不会在当前目前找可执行文件一样。
LIBRARY_PATH和LD_LIBRARY_PATH是Linux下的两个环境变量,二者的含义和作用分别如下:
LIBRARY_PATH环境变量用于在程序编译期间查找动态链接库时指定查找共享库的路径,例如,指定gcc编译需要用到的动态链接库的目录。
LD_LIBRARY_PATH环境变量用于在程序加载运行期间查找动态链接库时指定除了系统默认路径之外的其他路径.注意,LD_LIBRARY_PATH中指定的路径会在系统默认路径之前进行查找。
区别与使用:
开发时,设置LIBRARY_PATH,以便gcc能够找到编译时需要的动态链接库。
发布时,设置LD_LIBRARY_PATH,以便程序加载运行时能够自动找到需要的动态链接库。
GCC里的链接器的选项是 -rpath 和 -rpath-link,看了下 man ld,大致是这个意思:
GCC链接选项-L,-rpath-link和-rpath.-L: “链接”的时候,去找的目录,也就是所有的 -lFOO 选项里的库,都会先从 -L 指定的目录去找,然后是默认的地方。
-rpath_link :用于“链接”的时候的(GCC程序编译阶段-研发),例如你显示指定的需要 FOO.so,但是 FOO.so 本身是需要 BAR.so 的,后者你并没有指定,而是 FOO.so 引用到它,这个时候,会先从 -rpath-link 给的路径里找。-rpath-link 则只用于链接时。
-rpath: “运行”的时候,去找的目录(程序执行阶段-运维)。运行的时候,要找 .so 文件,会从这个选项里指定的地方去找。对于交叉编译,只有配合 --sysroot 选项才能起作用。
也就是说,-rpath指定的路径会被记录在生成的可执行程序中,用于运行时。
链接库
201305
第一类是静态链接的可执行程序.
静态可执行程序包含执行所需的所有函数 — 换句话说,它们是“完整的”。因为这一原因,静态可执行程序不依赖任何外部库就可以运行。
第二类是动态链接的可执行程序。
静态可执行程序与动态可执行程序比较
我们可以用 ldd 命令来确定某一特定可执行程序是否为静态链接的:
ldd /bin/ln
libc.so.6 => /lib/libc.so.6 (0x40021000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)
如您所见,ln 依赖外部共享库 libc.so.6 和 ld-linux.so.2。
通常,动态链接的程序比其静态链接的等价程序小得多。
动态装入器
那么,如果动态可执行程序不包含运行所需的所有函数,Linux 的哪部分负责将这些程序和所有必需的共享库一起装入,以使它们能正确执行呢?
答案是动态装入器(dynamic loader),它实际上是您在 ln 的 ldd(相关的库清单)清单中看到的作为共享库相关性列出的 ld-linux.so.2 库。
动态装入器负责装入动态链接的可执行程序运行所需的共享库 。
现在,让我们迅速查看一下动态装入器如何在系统上找到适当的共享库:ld.so.conf
动态装入器找到共享库要依靠两个文件 — /etc/ld.so.conf 和 /etc/ld.so.cache。
ld.so.conf 文件包含一个目录(/lib 和 /usr/lib 除外,它们会自动包含在其中)的清单,动态装入器将在其中查找共享库。
ld.so.cache 但是在动态装入器能“看到”这一信息之前,必须将它转换到 ld.so.cache 文件中。可以通过运行 ldconfig 命令做到这一点:
ldconfig 当 ldconfig 操作结束时,您会有一个最新的 /etc/ld.so.cache 文件,它反映您对 /etc/ld.so.conf 所做的更改。
从这一刻起,动态装入器在寻找共享库时会查看您在 /etc/ld.so.conf 中指定的所有新目录。
ldconfig 技巧
要查看 ldconfig 可以“看到”的所有共享库,请输入:ldconfig -p | less
还有另一个方便的技巧可以用来配置共享库路径(LD_LIBRARY_PATH)。
有时候您希望告诉动态装入器在尝试任何 /etc/ld.so.conf 路径以前先尝试使用特定目录中的共享库。(LD_LIBRARY_PATH指定的,貌似无法在lddconfig -p中看到)
LD_LIBRARY_PATH 要指示动态装入器首先检查某个目录,请将 LD_LIBRARY_PATH 变量设置成您希望搜索的目录。多个路径之间用冒号分隔;例如:
export LD_LIBRARY_PATH="/usr/lib/old:/opt/lib" 如果仍不能满足一些共享库相关性要求,则转回到 /etc/ld.so.conf 中指定的库。
ldd命令介绍及使用方法
20130517
在制作自己的发行版时经常需要判断某条命令需要哪些共享库文件的支持,以确保指定的命令在独立的系统内可以可靠的运行;
在Linux环境下通过ldd命令即可实现,在终端下执行:
ldd /bin/ls (通常使用"-v"或"--verbose"选项来显示所依赖的动态连接库的尽可能的详细信息)即可得到/bin/ls命令的相关共享库文件列表.
ldd的作用是打印可执行档依赖的共享库文件。它是glibc的一部分.
$ ldd --version
ldd (GNU libc) 2.12
但是ldd本身不是一个程序,而仅是一个shell脚本:
ldd可以获得的共享库文件,其实是通过读取ldconfig命令组建起来的文件(/etc/ld.so.cache)。
ldd命令其实是依靠设置一些环境变量而实现的(也就是说ldd的作用只是设置一些环境变量的值)
但是ldd命令的本质是执行了:/lib/ld-linux.so.*
我们可以从以上的内容中(ls /usr中)发现:/lib/ld-linux.so.2 (0xb7fad000)。
$ ls -l /lib/ld-linux.so.*
lrwxrwxrwx 1 root root 9 2009-09-05 22:54 /lib/ld-linux.so.2 -> ld-2.9.so
刚编译后的文件可能是:/lib/ld.so。如果是libc5则是/lib/ld-linux.so.1, 而glibc2应该是/lib/ld-linux.so.2。
默认的共享库文件搜索/lib64优先于/usr/lib64,而且也只有这个2个目录。如果想要加入其他路径,则需要通过ldconfig命令配置相关文件。
一般ld-linux.so会按照以下顺序搜索共享库:
ll /lib64/ld-linux-x86-64.so.2
lrwxrwxrwx 1 root root 10 Jun 3 06:42 /lib64/ld-linux-x86-64.so.2 -> ld-2.12.so 这样ldd --version显示的就是2.12版本.
1、DT_RPATH或DT_RUNPATH段
2、环境变量LD_LIBRARY_PATH
3、/etc/ld.so.cache文件中的路径.但如果可执行程序在连接时候添加了-z nodeflib选项,则跳过。#貌似3,4是反的吧?...
4、默认路径/lib和/usr/lib.但如果添加了-z nodeflib,则跳过。
ldd显示可执行模块的dependency的工作原理,其实质是通过ld-linux.so(elf动态库的装载器)来实现的。
我们知道,ld-linux.so模块会先于executable模块程序工作,并获得控制权,因此当上述的那些环境变量被设置时,ld-linux.so显示可执行模块的dependency。
实际上可以直接执行ld-linux.so模块,如:/lib/ld-linux.so.2 --list program(这相当于ldd program)ldd命令使用方法(摘自ldd --help)
ldd 输出在命令行上指定的每个程序需要的共享库。
ldd -v /bin/ls 可以显示很多调用的共享库
选项
--version
打印ldd的版本号
-v --verbose
打印所有信息,例如包括符号的版本信息
-d --data-relocs
执行符号重部署,并报告缺少的目标对象(只对ELF格式适用)
-r --function-relocs
对目标对象和函数执行重新部署,并报告缺少的目标对象和函数(只对ELF格式适用)
--help 用法信息
如果命令行中给定的库名字包含'/',这个程序的libc5版本将使用它作为库名字;否则它将在标准位置搜索库。运行一个当前目录下的共享库,加前缀"./"。
如果使用 ldd 命令时没有找到对应的共享库文件和其具体位置,可能是两种情况引起的:
共享库没有安装在该系统中;
共享库保存在 /etc/ld.so.conf 文件列出的搜索路径之外的位置。
通常情况下,许多开放源代码的程序或函数库都会默认将自己安装到 /usr/local 目录下的相应位置(如:/usr/local/bin 或 /usr/local/lib),以便与系统自身的程序或函数库相区别。而许多 Linux 系统的 /etc/ld.so.conf 文件中默认又不包含 /usr/local/lib。因此,往往会出现已经安装了共享库,但是却无法找到共享库的情况。

浙公网安备 33010602011771号