ldconfig - configure dynamic linker run-time bindings (配置动态链接器运行时绑定)
ldconfig creates the necessary links and cache to the most recent shared libraries found in the directories specified on the command line, in the file /etc/ld.so.conf, and in the trusted directories, /lib and /usr/lib (on some 64-bit architectures such as x86-64, /lib and /usr/lib are the trusted directories for 32-bit libraries, while /lib64 and /usr/lib64 are used for 64-bit libraries).
ldconfig 创建必要的链接并缓存在命令行指定的目录中、文件 /etc/ld.so.conf 和受信任目录 /lib and /usr/lib 中找到的最新共享库。某些 64 位体系结构 (如 x86-64) /lib and /usr/lib 是 32 位库的可信目录,而 /lib64 and /usr/lib64 用于 64 位库。
The cache is used by the run-time linker, ld.so or ld-linux.so. ldconfig checks the header and filenames of the libraries it encounters when determining which versions should have their links updated.
缓存由运行时链接程序 ld.so or ld-linux.so 使用。在确定哪些版本的链接更新时,ldconfig 会检查它遇到的库的头文件名和文件名。
ldconfig will attempt to deduce the type of ELF libs (i.e., libc5 or libc6/glibc) based on what C libs, if any, the library was linked against.
ldconfig 将尝试根据库链接的 C lib (如果有的话) 推断出 ELF 库的类型 (i.e., libc5 or libc6/glibc)。
Some existing libs do not contain enough information to allow the deduction of their type. Therefore, the /etc/ld.so.conf file format allows the specification of an expected type. This is used only for those ELF libs which we can not work out. The format is “dirname=TYPE”, where TYPE can be libc4, libc5, or libc6. (This syntax also works on the command line.) Spaces are not allowed. Also see the -p option. ldconfig should normally be run by the superuser as it may require write permission on some root owned directories and files.
一些现有的库不包含足够的信息以允许推断其类型。因此 /etc/ld.so.conf 文件格式允许指定期望的类型。这仅用于那些我们无法解决的 ELF 库。格式为 dirname=TYPE,其中 TYPE 可以是 libc4, libc5, or libc6。(此语法也适用于命令行。) 不允许使用空格。另请参阅 -p 选项。ldconfig 通常应由超级用户运行,因为它可能需要对某些 root 拥有的目录和文件具有写权限。
bind [baɪnd]:vi. 结合,装订,有约束力,过紧 vt. 绑,约束,装订,包扎,凝固 n. 捆绑,困境,讨厌的事情,植物的藤蔓
deduce [dɪ'djuːs]:vt. 推论,推断,演绎出
ldconfig 通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手动运行这个命令。
ldconfig 主要是在默认搜寻目录 (/lib and /usr/lib) 以及动态库配置文件 /etc/ld.so.conf 内所列的目录下,搜索出可共享的动态链接库 (lib*.so.*),进而创建出动态装入程序 (ld.so or ld-linux.so) 所需的链接和缓存文件。缓存文件默认为 /etc/ld.so.cache,此文件保存有已排好序的动态链接库名字列表。
1. OPTIONS
-c fmt, --format=fmt
(Since glibc 2.2) Cache format to use: old, new, or compat (default).
-C cache
Use cache instead of /etc/ld.so.cache.
-f conf
Use conf instead of /etc/ld.so.conf.
-i, --ignore-aux-cache
(Since glibc 2.7) Ignore auxiliary cache file.
auxiliary [ɔːɡˈzɪliəri]:adj. 辅助的,副的,附加的,(发动机、设备等) 备用的 n. 助动词,辅助者,辅助物,附属机构,(北美) 志愿队,(海军的) 辅助舰队
expert ['ekspɜːt]:n. 专家,行家,能手 adj. 熟练的,内行的,老练的 v. 当专家
individual [ˌɪndɪˈvɪdʒʊəl]:adj. 个人的,个别的,独特的 n. 个人,个体
-l
(Since glibc 2.2) Library mode. Manually link individual libraries. Intended for use by experts only.
-n
Only process directories specified on the command line. Don’t process the trusted directories, nor those specified in /etc/ld.so.conf. Implies -N.
仅处理命令行上指定的目录。不要处理受信任的目录,也不要处理 /etc/ld.so.conf 中指定的目录。意味着 -N。
使用此选项时,ldconfig 仅扫描命令行指定的目录,不扫描默认目录 (/lib and /usr/lib),也不扫描配置文件 /etc/ld.so.conf 所列的目录。
-N
Don’t rebuild the cache. Unless -X is also specified, links are still updated.
不要重建缓存。除非还指定了 -X,否则链接仍会更新。
此选项指示 ldconfig 不重建缓存文件 (/etc/ld.so.cache)。若未用 -X 选项,ldconfig 照常更新文件的链接。
-p, --print-cache
Print the lists of directories and candidate libraries stored in the current cache.
打印存储在当前缓存中的目录和候选库列表。
-r root
Change to and use root as the root directory.
-v, --verbose
Verbose mode. Print current version number, the name of each directory as it is scanned, and any links that are created. Overrides quiet mode.
详细模式。打印当前版本号,扫描时每个目录的名称以及创建的任何链接。覆盖 quiet 模式。
使用此选项时,ldconfig 将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的链接的名字。
-V, --version
Print program version.
-X
Don’t update links. Unless -N is also specified, the cache is still rebuilt.
此选项指示 ldconfig 不更新文件的链接。若未用 -N 选项,则缓存文件正常更新。
verbose [vɜː'bəʊs]:adj. 冗长的,啰嗦的
2. FILES
/lib/ld.so - Run-time linker/loader.
/etc/ld.so.conf - File containing a list of directories, one per line, in which to search for libraries. (包含目录列表的文件,每行一个,用于搜索库。)
/etc/ld.so.cache - File containing an ordered list of libraries found in the directories specified in /etc/ld.so.conf, as well as those found in the trusted directories. (包含在 /etc/ld.so.conf 中指定的目录中找到的库的有序列表的文件,以及在受信任目录中找到的库。)
3. ldconfig -p
guipc@deepnorth01:~$ ldconfig -p
1139 libs found in cache `/etc/ld.so.cache'
libzvbi.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi.so.0
libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi-chains.so.0
libzmq.so.5 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzmq.so.5
......
4. ldconfig -p | grep cudnn
guipc@deepnorth01:~$ ldconfig -p | grep cudnn
libcudnn.so.7 (libc6,x86-64) => /usr/local/cuda/lib64/libcudnn.so.7
libcudnn.so.6 (libc6,x86-64) => /usr/local/cuda-8.0/lib64/libcudnn.so.6
guipc@deepnorth01:~$
5. ldconfig -p | grep cuda
guipc@deepnorth01:~$ ldconfig -p | grep cuda
libnvrtc.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnvrtc.so.10.0
libnvrtc.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvrtc.so
libnvrtc-builtins.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnvrtc-builtins.so.10.0
libnvrtc-builtins.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvrtc-builtins.so
libnvjpeg.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnvjpeg.so.10.0
libnvjpeg.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvjpeg.so
libnvgraph.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnvgraph.so.10.0
libnvgraph.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvgraph.so
libnvblas.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnvblas.so.10.0
libnvblas.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvblas.so
libnvToolsExt.so.1 (libc6,x86-64) => /usr/local/cuda/lib64/libnvToolsExt.so.1
libnvToolsExt.so (libc6,x86-64) => /usr/local/cuda/lib64/libnvToolsExt.so
libnpps.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnpps.so.10.0
libnpps.so (libc6,x86-64) => /usr/local/cuda/lib64/libnpps.so
libnppitc.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppitc.so.10.0
libnppitc.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppitc.so
libnppisu.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppisu.so.10.0
libnppisu.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppisu.so
libnppist.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppist.so.10.0
libnppist.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppist.so
libnppim.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppim.so.10.0
libnppim.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppim.so
libnppig.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppig.so.10.0
libnppig.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppig.so
libnppif.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppif.so.10.0
libnppif.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppif.so
libnppidei.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppidei.so.10.0
libnppidei.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppidei.so
libnppicom.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppicom.so.10.0
libnppicom.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppicom.so
libnppicc.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppicc.so.10.0
libnppicc.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppicc.so
libnppial.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppial.so.10.0
libnppial.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppial.so
libnppc.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libnppc.so.10.0
libnppc.so (libc6,x86-64) => /usr/local/cuda/lib64/libnppc.so
libicudata.so.55 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libicudata.so.55
libcusparse.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcusparse.so.10.0
libcusparse.so (libc6,x86-64) => /usr/local/cuda/lib64/libcusparse.so
libcusolver.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcusolver.so.10.0
libcusolver.so (libc6,x86-64) => /usr/local/cuda/lib64/libcusolver.so
libcurand.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcurand.so.10.0
libcurand.so.8.0 (libc6,x86-64) => /usr/local/cuda-8.0/lib64/libcurand.so.8.0
libcurand.so (libc6,x86-64) => /usr/local/cuda/lib64/libcurand.so
libcuinj64.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcuinj64.so.10.0
libcuinj64.so (libc6,x86-64) => /usr/local/cuda/lib64/libcuinj64.so
libcufftw.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcufftw.so.10.0
libcufftw.so (libc6,x86-64) => /usr/local/cuda/lib64/libcufftw.so
libcufft.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcufft.so.10.0
libcufft.so (libc6,x86-64) => /usr/local/cuda/lib64/libcufft.so
libcudnn.so.7 (libc6,x86-64) => /usr/local/cuda/lib64/libcudnn.so.7
libcudnn.so.6 (libc6,x86-64) => /usr/local/cuda-8.0/lib64/libcudnn.so.6
libcudart.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcudart.so.10.0
libcudart.so.8.0 (libc6,x86-64) => /usr/local/cuda-8.0/lib64/libcudart.so.8.0
libcudart.so (libc6,x86-64) => /usr/local/cuda/lib64/libcudart.so
libcuda.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libcuda.so.1
libcuda.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libcuda.so
libcublas.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libcublas.so.10.0
libcublas.so.8.0 (libc6,x86-64) => /usr/local/cuda-8.0/lib64/libcublas.so.8.0
libcublas.so (libc6,x86-64) => /usr/local/cuda/lib64/libcublas.so
libaccinj64.so.10.0 (libc6,x86-64) => /usr/local/cuda/lib64/libaccinj64.so.10.0
libaccinj64.so (libc6,x86-64) => /usr/local/cuda/lib64/libaccinj64.so
libOpenCL.so.1 (libc6,x86-64) => /usr/local/cuda/lib64/libOpenCL.so.1
libOpenCL.so (libc6,x86-64) => /usr/local/cuda/lib64/libOpenCL.so
guipc@deepnorth01:~$
6. ldconfig
ldconfig 是一个动态链接库管理命令,目的为了让动态链接库为系统所共享。
-
/lib and /usr/lib 目录添加动态链接库,不需要修改 /etc/ld.so.conf,添加完库后需要调用 ldconfig,不然会找不到 library。
-
向 /lib and /usr/lib 目录之外的路径添加动态链接库,需要修改 /etc/ld.so.conf,然后调用 ldconfig,不然会找不到 library。
例如安装 MySQL 到 /usr/local/mysql,MySQL 的 library 在 /usr/local/mysql/lib 目录下,此时需要在 /etc/ld.so.conf 文件中添加一行 /usr/local/mysql/lib,保存后执行 ldconfig,library 才能在程序运行时被找到。
sudo echo "/usr/local/mysql/lib" >> /etc/ld.so.conf
-
向 /lib and /usr/lib 目录之外的路径添加动态链接库,不在 /etc/ld.so.conf 中添加路径 (或者是没有权限添加)。可以通过 export 一个全局变量 LD_LIBRARY_PATH,然后运行程序的时候就会去这个目录中找 library。这是一种临时解决方案,在没有权限或临时需要的时候使用。
vim ~/.bashrc
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
source ~/.bashrc
- ldconfig 命令执行都与运行程序时有关,跟编译时一点关系都没有。编译的时候还是需要加 -L,不要混淆。
- 不管执行了任何关于 library 的变动,最好都 ldconfig 一下,不然会出现一些意想不到的问题。
libcudnn.so.6.0.21 文件头中含有库名相关的信息 (即含有 libcudnn.so.6,可用 strings 命令查看),仅通过修改文件名以冒充某一被识别的库 (例如 libcudnn.so.7.5.0) 是行不通的。可在编译库的 Makefile 中直接修改配置信息,指定特别的库名。
strong@foreverstrong:~$ ls /usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21
/usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21
strong@foreverstrong:~$
strong@foreverstrong:~$ ll /usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21
-rwxr-xr-x 1 root root 154322864 Oct 12 2017 /usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21*
strong@foreverstrong:~$
strong@foreverstrong:~$ strings /usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21 | less
strong@foreverstrong:~$
strong@foreverstrong:~$ strings /usr/local/cuda-8.0/lib64/libcudnn.so.6.0.21 | grep libcudnn.so
libcudnn.so.6
strong@foreverstrong:~$
guipc@deepnorth01:~$ ls /usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0
/usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0
guipc@deepnorth01:~$
guipc@deepnorth01:~$ ll /usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0
-rwxr-xr-x 1 root root 356012392 8月 7 17:19 /usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0*
guipc@deepnorth01:~$
guipc@deepnorth01:~$ strings /usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0 | less
guipc@deepnorth01:~$
guipc@deepnorth01:~$ strings /usr/local/cuda-10.0/lib64/libcudnn.so.7.5.0 | grep libcudnn.so
libcudnn.so.7
guipc@deepnorth01:~$
Linux 下的共享库机制采用了类似于高速缓存的机制,将库信息保存在 /etc/ld.so.cache 里面。程序链接时,首先从这个文件里面查找,然后再到 ld.so.conf 的路径里面去详细找。修改了 ld.so.conf 需要重新运行一下 ldconfig。
内存的访问速度远远大于硬盘的访问速度。如果将常用的动态函数库加载到内存中 (高速缓存,cache),当软件要使用动态函数库时,就不需要重新从硬盘里读出,这样就可以提高动态函数库的读取速度。这个时候需要 ldconfig 与 /etc/ld.so.conf 的帮助。
将动态函数库加载到高速缓存 (cache) 中的过程:
- 要在 /etc/ld.so.conf 中添加想要读入高速缓存中的动态函数库所在的目录。注意,此处是目录而不是文件。
- 利用 ldconfig 命令执行将文件 /etc/ld.so.conf 的数据读入高速缓存中。
- 同时在 /etc/ld.so.cache 文件中记录数据。
事实上,ldconfig 还可以用来判断动态函数库的链接信息。
当你希望动态函数库的相关链接可以读入到高速缓存中时,可以将动态函数库所在的目录名称写入 /etc/ld.so.conf 中,然后执行 ldconfig。
sudo vim /etc/profile
添加系统应用程序的搜索路径,对所有用户有效。然后 source /etc/profile 保证设置立即生效,或者重新打开一个 terminal。
sudo vim /etc/ld.so.conf
将当前路径 .
和 /usr/local/lib
默认搜索路径,sudo ldconfig。
include /etc/ld.so.conf.d/*.conf
include /usr/local/lib
include .
6.1 /etc/ld.so.conf
guipc@deepnorth01:~$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
guipc@deepnorth01:~$
6.2 Ubuntu 16.04 安装 CUDA Toolkit 10.0
Please make sure that
- PATH includes /usr/local/cuda-10.0/bin
- LD_LIBRARY_PATH includes /usr/local/cuda-10.0/lib64, or, add /usr/local/cuda-10.0/lib64 to /etc/ld.so.conf and run ldconfig as root
To uninstall the CUDA Toolkit, run the uninstall script in /usr/local/cuda-10.0/bin
Please see CUDA_Installation_Guide_Linux.pdf in /usr/local/cuda-10.0/doc/pdf for detailed information on setting up CUDA.
6.3 Ubuntu 16.04 安装 CUDA Toolkit 8.0
Please make sure that
- PATH includes /usr/local/cuda-8.0/bin
- LD_LIBRARY_PATH includes /usr/local/cuda-8.0/lib64, or, add /usr/local/cuda-8.0/lib64 to /etc/ld.so.conf and run ldconfig as root
To uninstall the CUDA Toolkit, run the uninstall script in /usr/local/cuda-8.0/bin
Please see CUDA_Installation_Guide_Linux.pdf in /usr/local/cuda-8.0/doc/pdf for detailed information on setting up CUDA.
6.4 /sbin/ldconfig
ldconfig 在 /sbin/ 文件夹里面。
guipc@deepnorth01:~$ ll /sbin/ldconfig
-rwxr-xr-x 1 root root 387 2月 6 2019 /sbin/ldconfig*
guipc@deepnorth01:~$
7. ldconfig -p | less
2555 libs found in cache `/etc/ld.so.cache'
libzzipwrap-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipwrap-0.so.13
libzzipmmapped-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipmmapped-0.so.13
libzzipfseeko-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzipfseeko-0.so.13
libzzip-0.so.13 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzzip-0.so.13
libzvbi.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi.so.0
libzvbi-chains.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzvbi-chains.so.0
libzmq.so.5 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzmq.so.5
libzeitgeist-2.0.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzeitgeist-2.0.so.0
libzeitgeist-1.0.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzeitgeist-1.0.so.1
libzbar.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libzbar.so.0
libz.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libz.so.1
libz.so.1 (libc6) => /lib/i386-linux-gnu/libz.so.1
libz.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libz.so
libyelp.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libyelp.so.0
libyaml-0.so.2 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libyaml-0.so.2
libyajl.so.2 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libyajl.so.2
libx265.so.79 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libx265.so.79
libx264.so.148 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libx264.so.148
libx264.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libx264.so
libx86.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libx86.so.1
libxvidcore.so.4 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxvidcore.so.4
libxvidcore.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxvidcore.so
libxtables.so.11 (libc6,x86-64) => /lib/x86_64-linux-gnu/libxtables.so.11
libxslt.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxslt.so.1
libxslt.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxslt.so
libxshmfence.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxshmfence.so.1
libxshmfence.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxshmfence.so
libxml2.so.2 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxml2.so.2
libxml2.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxml2.so
libxklavier.so.16 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxklavier.so.16
libxkbfile.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxkbfile.so.1
libxkbcommon.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxkbcommon.so.0
libxkbcommon.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxkbcommon.so
libxkbcommon-x11.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxkbcommon-x11.so.0
libxine.so.2 (libc6,x86-64) => /usr/lib/libxine.so.2
libxine.so (libc6,x86-64) => /usr/lib/libxine.so
libxerces-c-3.1.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxerces-c-3.1.so
libxdot.so.4 (libc6,x86-64) => /usr/lib/libxdot.so.4
libxdot.so (libc6,x86-64) => /usr/lib/libxdot.so
libxcb.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb.so.1
libxcb.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb.so
libxcb-xv.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-xv.so.0
libxcb-xkb.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-xkb.so.1
libxcb-xinerama.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-xinerama.so.0
libxcb-xfixes.so.0 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-xfixes.so.0
libxcb-xfixes.so (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-xfixes.so
libxcb-util.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-util.so.1
libxcb-sync.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/libxcb-sync.so.1
:
strong@foreverstrong:~$ ldconfig -p | less
strong@foreverstrong:~$
Linux 系统上有两类根本不同的 Linux 可执行程序。第一类是静态链接的可执行程序。静态可执行程序包含执行所需的所有函数,它们是完整的。静态可执行程序不依赖任何外部库就可以运行。第二类是动态链接的可执行程序。
静态可执行程序与动态可执行程序的判断,ldd 命令可以确定某一特定可执行程序是否为静态链接的。
strong@foreverstrong:~$ ll /sbin/sfdisk
-rwxr-xr-x 1 root root 94280 Dec 1 2017 /sbin/sfdisk*
strong@foreverstrong:~$
strong@foreverstrong:~$ ll /sbin/fdisk
-rwxr-xr-x 1 root root 109632 Dec 1 2017 /sbin/fdisk*
strong@foreverstrong:~$
strong@foreverstrong:~$ ldd /sbin/fdisk
linux-vdso.so.1 => (0x00007ffd6c7ed000)
libfdisk.so.1 => /lib/x86_64-linux-gnu/libfdisk.so.1 (0x00007fb9c7bb6000)
libsmartcols.so.1 => /lib/x86_64-linux-gnu/libsmartcols.so.1 (0x00007fb9c7992000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fb9c7769000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb9c739f000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fb9c719a000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007fb9c6f59000)
/lib64/ld-linux-x86-64.so.2 (0x00007fb9c7e0e000)
strong@foreverstrong:~$
strong@foreverstrong:~$ ldd /sbin/sfdisk
linux-vdso.so.1 => (0x00007ffd9a75f000)
libfdisk.so.1 => /lib/x86_64-linux-gnu/libfdisk.so.1 (0x00007fbc6844d000)
libsmartcols.so.1 => /lib/x86_64-linux-gnu/libsmartcols.so.1 (0x00007fbc68229000)
libtinfo.so.5 => /lib/x86_64-linux-gnu/libtinfo.so.5 (0x00007fbc68000000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fbc67c36000)
libuuid.so.1 => /lib/x86_64-linux-gnu/libuuid.so.1 (0x00007fbc67a31000)
libblkid.so.1 => /lib/x86_64-linux-gnu/libblkid.so.1 (0x00007fbc677f0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fbc686a5000)
strong@foreverstrong:~$
动态可执行程序是不完整的程序,它依靠外部共享库来提供运行所需的许多函数。
7.1 动态链接相关性
查看 /bin/ln 依赖的所有共享库的列表,可以使用 ldd 命令:
strong@foreverstrong:~$ ls /bin/ln
/bin/ln
strong@foreverstrong:~$
strong@foreverstrong:~$
strong@foreverstrong:~$ ldd /bin/ln
linux-vdso.so.1 => (0x00007ffc733a3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff0416da000)
/lib64/ld-linux-x86-64.so.2 (0x00007ff041aa4000)
strong@foreverstrong:~$
/bin/ln 依赖外部共享库 linux-vdso.so.1、libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 和 /lib64/ld-linux-x86-64.so.2。动态链接的程序比其静态链接的等价程序小得多。静态链接的程序可以在某些低级维护任务中发挥作用。
7.2 动态装入器
如果动态可执行程序不包含运行所需的所有函数,Linux 的动态装入器 (dynamic loader) 负责将这些程序和所有必需的共享库一起装入,以使它们能正确执行。实际上是在 ldd /bin/ln 清单中看到的作为共享库相关性列出的 /lib64/ld-linux-x86-64.so.2 库。动态装入器负责装入动态链接的可执行程序运行所需的共享库。
动态装入器找到共享库要依靠两个文件 /etc/ld.so.conf 和 /etc/ld.so.cache。
strong@foreverstrong:~$ cat /etc/ld.so.conf
include /etc/ld.so.conf.d/*.conf
strong@foreverstrong:~$
ld.so.conf 文件包含一个所有目录 (/lib 和 /usr/lib 除外,它们会自动包含在其中) 的清单,动态装入器将在其中查找共享库。
在动态装入器能获取到这一信息之前,必须将它转换到 ld.so.cache 文件中。可以通过运行 ldconfig 命令来完成。当 ldconfig 操作结束时,你会有一个最新的 /etc/ld.so.cache 文件,它反映你对 /etc/ld.so.conf 所做的更改。从这一刻起,动态装入器在寻找共享库时会查看您在 /etc/ld.so.conf 中指定的所有新目录。
查看 ldconfig 可以获取到的所有共享库,请执行 ldconfig -p | less
。
配置共享库路径。有时候需要动态装入器在尝试任何 /etc/ld.so.conf 路径以前先尝试使用特定目录中的共享库。运行的较旧的应用程序不能与当前安装的库版本一起工作的情况下,这会比较方便。
要指示动态装入器首先检查某个目录,请将 LD_LIBRARY_PATH 变量设置成希望搜索的目录。多个路径之间用冒号分隔。
vim ~/.bashrc
export LD_LIBRARY_PATH=/usr/local/cuda-8.0/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
source ~/.bashrc
export LD_LIBRARY_PATH 后,如有可能,所有从当前 shell 启动的可执行程序都将使用 /usr/local/cuda-8.0/lib64 中的库,如果仍不能满足一些共享库相关性要求,则转回到 /etc/ld.so.conf 中指定的库。