Linux程序依赖动态链接库目录管理和案例分析

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 demo
        linux-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 demo
        linux-vdso.so.1 (0x00007ffeda58e000)
        libsum.so => not found
        libstdc++.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 demo
        linux-vdso.so.1 (0x00007ffe291dd000)
        libsum.so => not found
        libstdc++.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)

解决方案

  1. 手动export环境变量:export LD_LIBRARY_PATH=/root/libt/
  2. demo编译命令-Wl,-rpath加上库目录:-Wl,-rpath=/root/libt/
  3. 配置文件/etc/ld.so.conf和/etc/ld.so.conf.d/*.conf新增目录:在/etc/ld.so.conf文件新增一行:/root/libt/,或者,在/etc/ld.so.conf.d/新增一个.conf文件,文件内容新增一行:/root/libt/
  4. 将依赖库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 demo
        linux-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_H

extern "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.so

all: $(LIB)

$(LIB): $(OBJ)
	$(CC) $(LDFLAGS) -o $@ $^

sum.o: sum.cpp sum.h
	$(CC) $(CFLAGS) -o $@ sum.cpp

clean:
	rm -f $(OBJ) $(LIB)

DEMO=demo
OBJ_DEMO=main.o

$(DEMO): $(OBJ_DEMO) $(LIB)
	$(CC) -o $@ $^ -L. -lsum

clean: clean-demo

clean-demo:
	rm -f $(OBJ_DEMO) $(DEMO)

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值