Linux程序运行时查找依赖的动态链接库路径
- 编译时指定的
-rpath
:如果程序在编译时使用了-Wl,-rpath,
链接器选项,那么程序在运行时也会在这些指定的目录中搜索库。 - 环境变量
LD_LIBRARY_PATH
指定的目录:这是一个环境变量,可以包含一系列以冒号分隔的目录路径。程序会在这些目录中搜索动态链接库。 - 配置文件
/etc/ld.so.conf
和/etc/ld.so.conf.d/*.conf
:这些配置文件中定义的路径在LD_LIBRARY_PATH
之后被搜索。ldconfig
工具会读取这些文件。注意:如果新增了conf文件或内容,需要执行ldconfig命令才会生效。 - 默认系统库目录:如果以上方法都没有找到所需的库,动态链接器会搜索系统默认的库目录,通常是
/lib
和/usr/lib
。
ldd命令查看程序依赖的动态库和位置
(sdk) (python) -bash-5.1# ldd demolinux-vdso.so.1 (0x00007fff92f90000)libsum.so => /root/libt/libsum.so (0x00007f1efb4d4000)libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007f1efb2db000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007f1efb1ff000)libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007f1efb1e5000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007f1efafee000)/lib64/ld-linux-x86-64.so.2 (0x00007f1efb6d8000)
如果有些库查找失败会提示not found
(sdk) (python) -bash-5.1# ldd demolinux-vdso.so.1 (0x00007ffeda58e000)libsum.so => not foundlibstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fd7da2f3000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007fd7da217000)libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fd7da1fd000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007fd7da006000)/lib64/ld-linux-x86-64.so.2 (0x00007fd7da4ee000)
查看正在运行程序依赖的环境变量
Linux 的 /proc
文件系统提供了一个接口,可以查看正在运行的进程的详细信息,包括环境变量。你可以通过读取 /proc/[PID]/environ
文件来查看指定进程 ID (PID) 的环境变量。这个文件中的环境变量以 \0
(null 字符)分隔。 例如,要查看 PID 为 1234 的进程的环境变量,你可以使用以下命令,搜索LD_LIBRARY_PATH字段:
cat /proc/1234/environ
命令执行结果样例:(一长行根本不具备可视性。)
(sdk) (python) -bash-5.1# cat /proc/2841724/environ
SHELL=/bin/bashHISTCONTROL=ignoredupsHISTSIZE=1000HOSTNAME=localhostJAVA_HOME=/etc/alternatives/jre_1.8.0_openjdkJRE_HOME=/etc/alternatives/jre_1.8.0_openjdkPOCL_CACHE_DIR=/dl/.cacheorig_PS1=(python) \s-\v\$ PWD=/root/tmpLOGNAME=rootMOTD_SHOWN=pamorig_PATH=/dl/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/binHOME=/rootLANG=zh_CN.UTF-8VIRTUAL_ENV=/dl/pythonDLICC_PATH=/dl/sdk/binTOPHUB_LOCATION=NONECUDNN_INSTALL_DIR=/usr/local/cudaSSH_CONNECTION=10.34.6.23 61476 10.38.174.68 22PYTHONPATH=/dl/sdk/python/nne:/dl/sdk/python:/dl/sdk/python/pycuda:/dl/sdk/python/tf_graph_transformer/python:/dl/sdk/python/dl_tf_bridge/python:/dl/sdk/python/tensorflow_dlnn/python:/dl/sdk/python/tvm/python:/dl/sdk/python/tvm/dl/python:TERM=xtermCPLUS_INCLUDE_PATH=/usr/local/cuda-10.1/include/:orig_LD_LIBRARY_PATH=orig_PYTHONPATH=USER=rootenv_dlnn_ACTIVATED=1SHLVL=1CUDA_INSTALL_DIR=/usr/local/cudaDLCI_CACHE_DIR=/dl/.cache/dlciCLASSPATH=.:/etc/alternatives/jre_1.8.0_openjdk/lib/dt.jar:/etc/alternatives/jre_1.8.0_openjdk/lib/tools.jar:/etc/alternatives/jre_1.8.0_openjdk/libLD_LIBRARY_PATH=/root/libt/PS1=(sdk) (python) \s-\v\$ SSH_CLIENT=10.34.6.23 61476 22LD_LIBARY_PATH=/root/libt/PATH=/dl/sdk/bin:/dl/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/etc/alternatives/jre_1.8.0_openjdk/bin:/etc/alternatives/jre_1.8.0_openjdk/bin:/usr/bin/flashupdt:/root/binMAIL=/var/spool/mail/rootSSH_TTY=/dev/pts/5OLDPWD=/root_=./demo
所以,为了更易于阅读,你可以使用 tr命令将 null 字符替换为换行符,快速找到LD_LIBRARY_PATH字段:
cat /proc/1234/environ | tr '\0' '\n'
命令执行结果样例:
(sdk) (python) -bash-5.1# cat /proc/2841724/environ | tr '\0' '\n'
SHELL=/bin/bash
HISTCONTROL=ignoredups
HISTSIZE=1000
HOSTNAME=localhost
JAVA_HOME=/etc/alternatives/jre_1.8.0_openjdk
JRE_HOME=/etc/alternatives/jre_1.8.0_openjdk
POCL_CACHE_DIR=/dl/.cache
orig_PS1=(python) \s-\v\$
PWD=/root/tmp
LOGNAME=root
MOTD_SHOWN=pam
orig_PATH=/dl/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
HOME=/root
LANG=zh_CN.UTF-8
VIRTUAL_ENV=/dl/python
DLICC_PATH=/dl/sdk/bin
TOPHUB_LOCATION=NONE
CUDNN_INSTALL_DIR=/usr/local/cuda
SSH_CONNECTION=10.34.6.23 61476 10.38.174.68 22
PYTHONPATH=/dl/sdk/python/nne:/dl/sdk/python:/dl/sdk/python/pycuda:/dl/sdk/python/tf_graph_transformer/python:/dl/sdk/python/dl_tf_bridge/python:/dl/sdk/python/tensorflow_dlnn/python:/dl/sdk/python/tvm/python:/dl/sdk/python/tvm/dl/python:
TERM=xterm
CPLUS_INCLUDE_PATH=/usr/local/cuda-10.1/include/:
orig_LD_LIBRARY_PATH=
orig_PYTHONPATH=
USER=root
env_dlnn_ACTIVATED=1
SHLVL=1
CUDA_INSTALL_DIR=/usr/local/cuda
DLCI_CACHE_DIR=/dl/.cache/dlci
CLASSPATH=.:/etc/alternatives/jre_1.8.0_openjdk/lib/dt.jar:/etc/alternatives/jre_1.8.0_openjdk/lib/tools.jar:/etc/alternatives/jre_1.8.0_openjdk/lib
LD_LIBRARY_PATH=/root/libt/
PS1=(sdk) (python) \s-\v\$
SSH_CLIENT=10.34.6.23 61476 22
LD_LIBARY_PATH=/root/libt/
PATH=/dl/sdk/bin:/dl/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/etc/alternatives/jre_1.8.0_openjdk/bin:/etc/alternatives/jre_1.8.0_openjdk/bin:/usr/bin/flashupdt:/root/bin
MAIL=/var/spool/mail/root
SSH_TTY=/dev/pts/5
OLDPWD=/root
_=./demo
demo示例
demo程序位置:/root/tmp/demo
libsum.so库位置:/root/libt/libsum.so
设置环境变量前执行程序,报错提示找不到库:
(sdk) (python) -bash-5.1# ./demo
./demo: error while loading shared libraries: libsum.so: cannot open shared object file: No such file or directory
通过命令ldd查看依赖库信息:
(sdk) (python) -bash-5.1# ldd demolinux-vdso.so.1 (0x00007ffe291dd000)libsum.so => not foundlibstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fd02ff4c000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007fd02fe70000)libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fd02fe56000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007fd02fc5f000)/lib64/ld-linux-x86-64.so.2 (0x00007fd030147000)
解决方案
- 手动export环境变量:export LD_LIBRARY_PATH=/root/libt/
- demo编译命令-Wl,-rpath加上库目录:-Wl,-rpath=/root/libt/
- 配置文件/etc/ld.so.conf和/etc/ld.so.conf.d/*.conf新增目录:在/etc/ld.so.conf文件新增一行:/root/libt/,或者,在/etc/ld.so.conf.d/新增一个.conf文件,文件内容新增一行:/root/libt/
- 将依赖库libsum.so拷贝至系统默认目录/lib/:cp /root/libt/libsum.so /lib/
注意:1方法只对当前会话有效,每次程序启动前都需要设置,3和4方法设置后需要执行ldconfig命令才会生效。
通过以上任何一种方法设置成功后,ldd查看程序链接信息正常,程序启动正常。
(sdk) (python) -bash-5.1# export LD_LIBRARY_PATH=/root/libt/
(sdk) (python) -bash-5.1# ./demo
The sum is: 8
(sdk) (python) -bash-5.1#
(sdk) (python) -bash-5.1#
(sdk) (python) -bash-5.1# ldd demolinux-vdso.so.1 (0x00007fff54b6a000)libsum.so => /root/libt/libsum.so (0x00007fa6085c1000)libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fa6083c8000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007fa6082ec000)libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fa6082d2000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007fa6080db000)/lib64/ld-linux-x86-64.so.2 (0x00007fa6087c5000)
demo源码
//sum.h
#ifndef SUM_H
#define SUM_Hextern "C" int add(int a, int b);#endif // SUM_H
//sum.cpp
#include "sum.h"extern "C" int add(int a, int b) {return a + b;
}
//main.cpp
#include <iostream>
#include "sum.h"int main() {int result = add(5, 3);std::cout << "The sum is: " << result << std::endl;int n;std::cin >> n;return 0;
}
#Makefile
CC=g++
CFLAGS=-c -fPIC
LDFLAGS=-shared
OBJ=sum.o
LIB=libsum.soall: $(LIB)$(LIB): $(OBJ)$(CC) $(LDFLAGS) -o $@ $^sum.o: sum.cpp sum.h$(CC) $(CFLAGS) -o $@ sum.cppclean:rm -f $(OBJ) $(LIB)DEMO=demo
OBJ_DEMO=main.o$(DEMO): $(OBJ_DEMO) $(LIB)$(CC) -o $@ $^ -L. -lsumclean: clean-democlean-demo:rm -f $(OBJ_DEMO) $(DEMO)