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

相关文章

java不依赖临时变量交换两个变量的值

java不依赖临时变量交换两个变量的值 1.简单易懂的实现方式     int a=1,b=2;     int temp = 0;     temp = a;     a = b;     b= temp; 2.算术算法 int a=1,b=2; a = a+b;// a = 1+2  b = a-b;// b = a-b --> b=3-2 -->1 a = a -b;/

Java内存管理 - 垃圾收集算法

我们都知道Java 中垃圾收集器 [GC] 的功能。但只有少数人试图深入了解垃圾收集的工作原理。你不是其中之一,这就是你在这里的原因。 在这个Java内存管理教程中,我们将尝试了解Java垃圾收集的当前算法,我们将了解这些算法的演变。 目录1. Java中的内存管理2.引用计数机制3.标记和清除机制4.停止并复制GC 5.分代停止和复制6.如何提高Java中的内存利用率 1.

Apache Shiro会话管理功能-07

Apache Shiro会话管理功能 会话是您的用户在使用您的应用程序时携带一段时间的数据桶。传统上,会话专用于Web或EJB环境。Shiro支持任何应用程序环境的会话。此外,Shiro还提供许多其他强大功能来帮助您管理会话。 特征 基于POJO / J2SE(IoC) - Shiro中的所有内容(包括会话和会话管理的所有方面)都是基于接口的,并使用POJO实现。这允许您使用任何与Ja

Linux命令学习之二

每日一结 ​               命令置换:是将一个命令的输出作为另一个命令的参数,命令格式如下: commond1 `command2` 其中,命令command2的输出将作为命令command1的参数,需要注意的是, 命令置换的单引号为ESC键下方的 ` 其意思就是说,先运行单引号内的命令,再将其命令作为

Linux命令学习之一

每日一结                                                                                        注:当用户不确定一个软件包的类型时, 可使用file命令查看文件类型

Linux文件I/O之一

每日一结(标准I/O)   一  库    本质 :一组实现函数接口 [printf,scanf,strcpy,strlen]   使用标准库好处:屏蔽底层细节,向上层提供统一的接口,提高程序的可移植性   windows 库 : *.dll  linux   库 : *.so    二 系统调用接口    本

关于 ZigBee WiFi Bluetooth 的分析

ZigBee: Zigbee是IEEE 802.15.4协议的代名词。根据这个协议规定的技术是一种短距离、低功耗的无线通信技术。其特点是近距离、低复杂度、自组织、低功耗、低数据速率、低成本。主要适合用于自动控制和远程控制领域,可以嵌入各种设备。简而言之,ZigBee就是一种便宜的,低功耗的近距离无线组网通讯技术。             ZigBee的主要优势:

Linux网络编程之五

每日一结 组播: ​ 网络地址: 一些特殊的组播地址:   一 组播包收和发 1.发送方 (1)创建用户数据报套接字 (2)填充组播地址和端口  (3)发送数据到组播地址 2.接收方  (1)创建用户数据报套接字 (2)加入组播组  struct ip_mreq mreq; mreq.imr_m

Linux网络编程之四

每日一结 一 UDP并发  核心思想:父进程接收到客户端的数据,就创建子进程,在子进程中创建一个新的套接字  和客户端交互  int do_client(接受客户端地址,数据,数据长度) { 1.创建用户数据报套接字  2.自动分配地址  3.处理数据[例如:输出数据内容] 4.通过新创建的套接字将数据回发给客户端  w

Linux网络编程之三

每日一结 Tftp服务器的实现: server.c ​       client.c     代码分析如下:     一 Linux IO模型  (1)阻塞IO  (2)非阻塞IO  非阻塞IO