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

2024-05-09 08:28

本文主要是介绍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 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)

解决方案

  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 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)

这篇关于Linux程序依赖动态链接库目录管理和案例分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/972897

相关文章

Linux线程之线程的创建、属性、回收、退出、取消方式

《Linux线程之线程的创建、属性、回收、退出、取消方式》文章总结了线程管理核心知识:线程号唯一、创建方式、属性设置(如分离状态与栈大小)、回收机制(join/detach)、退出方法(返回/pthr... 目录1. 线程号2. 线程的创建3. 线程属性4. 线程的回收5. 线程的退出6. 线程的取消7.

Linux下进程的CPU配置与线程绑定过程

《Linux下进程的CPU配置与线程绑定过程》本文介绍Linux系统中基于进程和线程的CPU配置方法,通过taskset命令和pthread库调整亲和力,将进程/线程绑定到特定CPU核心以优化资源分配... 目录1 基于进程的CPU配置1.1 对CPU亲和力的配置1.2 绑定进程到指定CPU核上运行2 基于

golang程序打包成脚本部署到Linux系统方式

《golang程序打包成脚本部署到Linux系统方式》Golang程序通过本地编译(设置GOOS为linux生成无后缀二进制文件),上传至Linux服务器后赋权执行,使用nohup命令实现后台运行,完... 目录本地编译golang程序上传Golang二进制文件到linux服务器总结本地编译Golang程序

Linux下删除乱码文件和目录的实现方式

《Linux下删除乱码文件和目录的实现方式》:本文主要介绍Linux下删除乱码文件和目录的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux下删除乱码文件和目录方法1方法2总结Linux下删除乱码文件和目录方法1使用ls -i命令找到文件或目录

MySQL中的LENGTH()函数用法详解与实例分析

《MySQL中的LENGTH()函数用法详解与实例分析》MySQLLENGTH()函数用于计算字符串的字节长度,区别于CHAR_LENGTH()的字符长度,适用于多字节字符集(如UTF-8)的数据验证... 目录1. LENGTH()函数的基本语法2. LENGTH()函数的返回值2.1 示例1:计算字符串

Spring Boot集成Druid实现数据源管理与监控的详细步骤

《SpringBoot集成Druid实现数据源管理与监控的详细步骤》本文介绍如何在SpringBoot项目中集成Druid数据库连接池,包括环境搭建、Maven依赖配置、SpringBoot配置文件... 目录1. 引言1.1 环境准备1.2 Druid介绍2. 配置Druid连接池3. 查看Druid监控

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

Linux在线解压jar包的实现方式

《Linux在线解压jar包的实现方式》:本文主要介绍Linux在线解压jar包的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux在线解压jar包解压 jar包的步骤总结Linux在线解压jar包在 Centos 中解压 jar 包可以使用 u

linux解压缩 xxx.jar文件进行内部操作过程

《linux解压缩xxx.jar文件进行内部操作过程》:本文主要介绍linux解压缩xxx.jar文件进行内部操作,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、解压文件二、压缩文件总结一、解压文件1、把 xxx.jar 文件放在服务器上,并进入当前目录#

Linux系统性能检测命令详解

《Linux系统性能检测命令详解》本文介绍了Linux系统常用的监控命令(如top、vmstat、iostat、htop等)及其参数功能,涵盖进程状态、内存使用、磁盘I/O、系统负载等多维度资源监控,... 目录toppsuptimevmstatIOStatiotopslabtophtopdstatnmon