Linux 查看程序(动态库)进程的依赖库的方法

Posted SongpingWang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux 查看程序(动态库)进程的依赖库的方法相关的知识,希望对你有一定的参考价值。

文章目录

当我们在linux上部署自己开发的项目程序时,项目代码与依赖库完整拷贝过去之后,直接运行我们自己的可执行程序,往往提示找不到所相关的.so库,会报错。
系统只会去默认搜寻目录(/lib和/usr/lib)下, 以及动态库配置文件(/etc/ld.so.conf和/etc/ld.so.conf.d/*.conf)里所列的目录下, 搜索可共享的动态库(格式如lib*.so*), 进而创建出动态装入程序*(ld.so)*所需的连接和缓存文件。因此,需要我们手动将路径添加进去。

1. 利用ldd查看可执行程序(动态库)的依赖库

使用 ldd -r XXX 查询动态库的依赖。关于undefined symbol使用 C++filt 查看

[user@localhost dist]$ ldd /usr/bin/bash
        linux-vdso.so.1 =>  (0x00007ffdbe9e0000)
        libtinfo.so.5 => /lib64/libtinfo.so.5 (0x00007fa7da66c000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007fa7da468000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fa7da09a000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa7da896000)

[user@localhost ocr_server]$ ldd libgims.so
        linux-vdso.so.1 =>  (0x00007ffca0de1000)
        libopencv_imgproc.so.405 => /usr/local/lib64/libopencv_imgproc.so.405 (0x00007f6dbb5ce000)
        libopencv_core.so.405 => /usr/local/lib64/libopencv_core.so.405 (0x00007f6dba3df000)
        libopencv_imgcodecs.so.405 => /usr/local/lib64/libopencv_imgcodecs.so.405 (0x00007f6db9e57000)
        libonnxruntime.so.1.11.1 => /home/user/onnxruntime/lib/libonnxruntime.so.1.11.1 (0x00007f6db8fef000)
        libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f6db8ce7000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f6db89e5000)
        libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f6db87cf000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f6db8401000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f6db81e5000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f6db7fe1000)
        libpng15.so.15 => /lib64/libpng15.so.15 (0x00007f6db7998000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f6dbd551000)

[wangsp@localhost ocr_server]$ ldd libASL_gcn_label.so  `部署到生产环境出现错误:not found`
        linux-vdso.so.1 => not found  
        libopencv_imgproc.so.405 => not found
        libopencv_core.so.405 => not found
        libopencv_imgcodecs.so.405 => not found
        libonnxruntime.so.1.11.1 => not found
        libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f1013e6a000)
        libm.so.6 => /lib64/libm.so.6 (0x00007f1013b68000)
        libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f1013950000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f1013582000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f1013366000)
        libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007f1012aef000)
        libpng15.so.15 => /lib64/libpng15.so.15 (0x00007f10128c4000)
        libtiff.so.5 => /lib64/libtiff.so.5 (0x00007f1012650000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f101785f000)
        libjbig.so.2.0 => /lib64/libjbig.so.2.0 (0x00007f1012444000)

方法:

  1. /etc/ld.so.conf.d 目录下创建 XXX_server.conf 文件,将该软件依赖的库路径添加进去
    echo /home/user/Project/XXX_server/ > /etc/ld.so.conf.d/XXX_server.conf
    执行生效
    ldconfig

  2. 或者:export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/custom/path
    或者:echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/your/custom/path/' >> ~/.bashrc

2. 利用pldd获取进程的内存映射信息,进程的依赖共享库

如下XXX即需要查询的程序名称
pldd $(ps -ef | grep XXX| grep -v grep | awk 'print $2')

[user@localhost laun]$ sudo pldd $(ps -ef | grep XXX | grep -v grep | awk 'print $2')
3172:   /home/user/laun/dist/XXX/XXX
linux-vdso.so.1
/lib64/libdl.so.2
/home/user/laun/dist/XXX/libz.so.1
/lib64/libpthread.so.0
/lib64/libc.so.6
/lib64/ld-linux-x86-64.so.2
/home/user/laun/dist/XXX/libpython3.6m.so.1.0
/lib64/libutil.so.1
/lib64/libm.so.6
/home/user/laun/dist/XXX/lib-dynload/_struct.cpython-36m-x86_64-linux-gnu.so
/home/user/laun/dist/XXX/lib-dynload/zlib.cpython-36m-x86_64-linux-gnu.so
...
/home/user/laun/dist/XXX/lib-dynload/_json.cpython-36m-x86_64-linux-gnu.so
/home/user/laun/dist/XXX/markupsafe/_speedups.cpython-36m-x86_64-linux-gnu.so
/home/user/laun/dist/XXX/lib-dynload/unicodedata.cpython-36m-x86_64-linux-gnu.so
./XXX/libgims.so
/usr/local/lib64/libopencv_imgproc.so.405
/usr/local/lib64/libopencv_core.so.405
/usr/local/lib64/libopencv_imgcodecs.so.405
/home/user/onnxruntime-linux-x64-1.11.1/lib/libonnxruntime.so.1.11.1
/lib64/libpng15.so.15
./XXX/libgmc.so
./XXX/libgcn_label.so
./XXX/libASL_gcn_label.so
./XXX/libiisis.so
./XXX/libit_dwmp.so
./XXX/libit_dwmp2.so
./XXX/liblgbm.so
/home/user/laun/dist/XXX/gevent/_gevent_c_imap.cpython-36m-x86_64-linux-gnu.so
/home/user/laun/dist/XXX/lib-dynload/_multiprocessing.cpython-36m-x86_64-linux-gnu.so

3. 利用pmap工具查询未知的可执行程序的依赖库

[user@localhost dist]$ objdump -p /usr/local/php/bin/php |grep NEEDED
  NEEDED               libcrypt.so.1
  NEEDED               librt.so.1
  NEEDED               libmysqlclient.so.18
  NEEDED               libmcrypt.so.4
  NEEDED               libiconv.so.2
  NEEDED               libcurl.so.4
  NEEDED               libm.so.6
  NEEDED               libdl.so.2
  NEEDED               libnsl.so.1
  NEEDED               libxml2.so.2
  NEEDED               libz.so.1
  NEEDED               libssl.so.10
  NEEDED               libcrypto.so.10
  NEEDED               libpthread.so.0
  NEEDED               libc.so.6
  NEEDED               libresolv.so.2

4. 利用pmap查看正在运行时的进程的依赖库

[user@localhost ~/software/pldd]$ ps -ef|grep php-fpm
root     26534     1  0  2014 ?        00:01:34 php-fpm: master process (/usr/local/php-5.3.29/etc/php-fpm.conf)
nobody   26535 26534  0  2014 ?        00:00:04 php-fpm: pool www          
nobody   26536 26534  0  2014 ?        00:00:05 php-fpm: pool www          
root     30510 30324  0 00:39 pts/0    00:00:00 grep php-fpm


[user@localhost ~/software/pldd]$ pmap 26534 |head 
26534:   php-fpm: master process (/usr/local/php-5.3.29/etc/php-fpm.conf)
0000000000400000  10452K r-x--  /usr/local/php-5.3.29/sbin/php-fpm
0000000001035000     76K rw---  /usr/local/php-5.3.29/sbin/php-fpm
0000000001048000    104K rw---    [ anon ]
0000000002a65000   3448K rw---    [ anon ]
000000311c600000    388K r-x--  /usr/lib64/libssl.so.1.0.1e
000000311c661000   2048K -----  /usr/lib64/libssl.so.1.0.1e
000000311c861000     16K r----  /usr/lib64/libssl.so.1.0.1e
000000311c865000     28K rw---  /usr/lib64/libssl.so.1.0.1e
000000311ce00000     92K r-x--  /lib64/libpthread-2.12.so

5. ln 命令

ln(link 其实link命令的缩写) 具体使用: ln [选项] 目标文件
选项有如下
-s 使用软连接
-b 删除,覆盖之前建立的链接
-d 允许超级用户制作目录的硬链接
-f 强制执行
-i 交互模式,文件存在则提示用户是否覆盖
-n 把符号链接视为一般目录
-v 显示详细的处理过程

6. version GLIBCXX_3.4.20 not found 错误解决

参考:Linux 批量依赖库拷贝(ldd)
version GLIBCXX_3.4.20 not found 错误解决
libstdc++.so.6: version `GLIBCXX_3.4.21‘ not found

7. 使用dlopen加载动态库

https://www.cnblogs.com/0xzhang/p/14460925.html
https://www.cnblogs.com/Anker/p/3746802.html

Linux下的静态库和动态库

静态库

可以把它想象成是一些代码的集合,在可执行程序运行前就已经加到了代码中,成为了执行程序的一部分,一般是以.a为后缀的文件名,Windows下后缀为.lib。静态库的命名也分为三部分,1、前缀:lib,2、库的名称:随意,如lisi,3、后缀:.a。

静态库优缺点

上面简单介绍了静态库,那它自然也会有优缺点,这里来介绍下它的优缺点。

优点:1、在最后,函数库是被打包到应用程序中的,实现函数本地化、寻址方便、高效。2、程序在运行的时候,与函数库没有关系,移植性更强。

缺点:1、消耗资源较大,每个进程在使用静态库的时候,都要复制一份才可以,这也就造成了内存的消耗。2、在程序更新、部署、发布的时候,使用静态库相对麻烦,如果一个静态库更新了,那它的应用程序都需要重新编译,再发送给用户,有的时候可能只是一个小的改动,但对于用户来说,会导致整个程序重新下载。

动态库

在程序编译时不会被连接到目标代码中,在后期运行时才会载入,不同的应用程序如果调用相同的库,内存中只有一份共享库的拷贝,也就避免了空间的浪费问题。一般以.so作为文件后缀名,也分为三部分:1、前缀:lib,2、库名称:自定义,3、后缀:.so

动态库优缺点

优点:1、节省内存2、部署、升级相对方便,只需要更换动态库,再重新启动服务即可。

缺点:1、加载速度比静态库慢2、移植性较差,需要把所有用到的动态库进行移植。

参考技术A linux下的静态库和动态库1.制作自己的动态库和静态库linux下动态库以.so结尾,静态库以.a结尾,它们都以lib开头,比如一个库名为net,那么它的全名应该是libnet.so或者libnet.a。我们有两个文件,hello.c和test.c,下面是两个文件的内容//hello.c
www.zhishiwu.com
#include
<stdio.h>void
my_lib_func()printf(Library
routine
called/r/n);//test.c#include
<stdio.h>
www.zhishiwu.com
int
main()my_lib_func();return
1;test.c调用了hello.c的方法,我们把hello.c封装成库文件。无论是静态库还是动态库,都是由.o文件组成,我们先把gcc
-c
hello.c生成.o文件制作静态库ar
crv
libmyhello.a
hello.o,ar是生成静态库的命令,libmyhello.a是我的静态库名。下一步就是在我的程序中使用静态库
可以看到已经有了Library
routine
called的结果,说明调用成功了。下面我们删除libmyhello.a,看看程序是否还是运行正常
我们发现程序依然运行正常,说明静态库已经连接进入我们的程序中制作动态库
www.zhishiwu.com
我们看见动态库libmyhello.so已经生成,下面继续使用
找不到库文件,这个时候我们把so文件拷贝到/usr/lib下面
运行成功2.动态库和静态库同时存在的调用规则我们可以发现,不论是动态库还是静态库,程序编译连接的时候都是加的参数-l,那么当他们同时存在的时候,程序会选择动态库还是静态库呢。我们做个尝试。
我们同时存在libmyhello.a和libmyhello.so,我们发现运行的时候,出现找不到动态库的错误,由此,我们可以得出结论,同时存在动态库和静态库的时候,gcc会优先选择动态库作者
梨树阳光

以上是关于Linux 查看程序(动态库)进程的依赖库的方法的主要内容,如果未能解决你的问题,请参考以下文章

如何查看和调试动态链接库的内存泄露

Linux下的静态库和动态库

Linux_动态库与静态库(制作与安装)

linux中动态库libXXX.so

linux找不到动态链接库 .so文件的解决方法

如何交叉编译 动态库