Fork me on GitHub

Linux命令——ldd和ldconfig

转自:Linux系统中“动态库”和“静态库”那点事儿

前言

在调试lua脚本的时候,报错。

我已经再lua脚本中更改了cpath

package.cpath = package.cpath .. ";/usr/local/lib/?.so"

而且在/usr/local/lib有liblualongnumber.so.0啊,怎么会找不到呢?

下文将介绍此问题的解决过程

理论部分

参考:

剖析可执行文件ELF组成

剖析.o文件ELF组成

目标文件

.symtab

编译

剖析gcc -v输出

静态库 VS 动态库

静态链接 VS 动态链接

Linux系统中“动态库”和“静态库”那点事儿

从源代码到进程

静态链接(Static Linking)

动态链接/动态加载

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。

静态库

这类库的名字一般是libxxx.a,xxx为库的名字。利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

动态库

这类库的名字一般是libxxx.M.N.so,同样的xxx为库的名字,M是库的主版本号,N是库的副版本号。当然也可以不要版本号,但名字必须有。相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。linux系统有几个重要的目录存放相应的函数库,如/lib /usr/lib。

当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。然而,对动态库而言,就不是这样。动态库会在执行程序内留下一个标记指明当程序执行时,首先必须载入这个库。由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。

有时候当我们的应用程序无法运行时,它会提示我们说它找不到什么样的库,或者哪个库的版本又不对等等之类的问题。那么应用程序它是怎么知道需要哪些库的呢?ldd命令(下文有介绍)就可以查看动态文件(可执行文件,动态库)依赖了那些文件。

Linux系统中动态链接库的配置文件一般在/etc/ld.so.conf文件内。这个文件内容比较有意思

include /etc/ld.so.conf.d/*.conf

他指向/etc/ld.so.conf.d/目录下所有conf文件。这些文件有志向了具体目录,那些目录下面就是Linux系统要找的共享对象。

root@ubuntu:/etc/ld.so.conf.d# ls
fakeroot-x86_64-linux-gnu.conf  libc.conf  x86_64-linux-gnu.conf
root@ubuntu:/etc/ld.so.conf.d# cat *
/usr/lib/x86_64-linux-gnu/libfakeroot
# libc default configuration
/usr/local/lib
# Multiarch support
/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu
root@ubuntu:/etc/ld.so.conf.d# ls -m /lib/x86_64-linux-gnu
device-mapper, ld-2.23.so, ld-linux-x86-64.so.2, libacl.so.1, libacl.so.1.1.0, libaio.so.1, libaio.so.1.0.1, libanl-2.23.so,
libanl.so.1, libapparmor.so.1, libapparmor.so.1.4.0, libatm.so.1, libatm.so.1.0.0, libattr.so.1, libattr.so.1.1.0, libaudit.so.1,
libaudit.so.1.0.0, libblkid.so.1, libblkid.so.1.1.0, libBrokenLocale-2.23.so, libBrokenLocale.so.1, libbsd.so.0, libbsd.so.0.8.2,
libbz2.so.1, libbz2.so.1.0, libbz2.so.1.0.4, libc-2.23.so, libcap.so.2, libcap.so.2.24, libcidn-2.23.so, libcidn.so.1, libcom_err.so.2,
libcom_err.so.2.1, libcrypt-2.23.so, libcrypto.so.1.0.0, libcryptsetup.so.4, libcryptsetup.so.4.6.0, libcrypt.so.1, libc.so.6,
libdbus-1.so.3, libdbus-1.so.3.14.6, libdevmapper-event-lvm2mirror.so, libdevmapper-event-lvm2raid.so,
libdevmapper-event-lvm2snapshot.so, libdevmapper-event-lvm2.so.2.02, libdevmapper-event-lvm2thin.so, libdevmapper-event.so.1.02.1,
libdevmapper.so.1.02.1, libdl-2.23.so, libdl.so.2, libdns-export.so.162, libdns-export.so.162.1.3, libe2p.so.2, libe2p.so.2.3,
libexpat.so.1, libexpat.so.1.6.0, libext2fs.so.2, libext2fs.so.2.4, libfdisk.so.1, libfdisk.so.1.1.0, libfuse.so.2, libfuse.so.2.9.4,
libgcc_s.so.1, libgcrypt.so.20, libgcrypt.so.20.0.5, libglib-2.0.so.0, libglib-2.0.so.0.4800.2, libgpg-error.so.0,
libgpg-error.so.0.17.0, libhistory.so.5, libhistory.so.5.2, libhistory.so.6, libhistory.so.6.3, libip4tc.so.0, libip4tc.so.0.1.0,
libip6tc.so.0, libip6tc.so.0.1.0, libiptc.so.0, libiptc.so.0.0.0, libisc-export.so.160, libisc-export.so.160.0.0, libjson-c.so.2,
libjson-c.so.2.0.0, libkeyutils.so.1, libkeyutils.so.1.5, libkmod.so.2, libkmod.so.2.3.0, liblvm2app.so.2.2, liblvm2cmd.so.2.02,
liblzma.so.5, liblzma.so.5.0.0, liblzo2.so.2, liblzo2.so.2.0.0, libm-2.23.so, libmemusage.so, libmnl.so.0, libmnl.so.0.1.0,
libmount.so.1, libmount.so.1.1.0, libm.so.6, libmvec-2.23.so, libmvec.so.1, libncurses.so.5, libncurses.so.5.9, libncursesw.so.5,
libncursesw.so.5.9, libnewt.so.0.52, libnewt.so.0.52.18, libnih.so.1, libnih.so.1.0.0, libnl-3.so.200, libnl-3.so.200.22.0,
libnl-genl-3.so.200, libnl-genl-3.so.200.22.0, libnsl-2.23.so, libnsl.so.1, libnss_compat-2.23.so, libnss_compat.so.2,
libnss_dns-2.23.so, libnss_dns.so.2, libnss_files-2.23.so, libnss_files.so.2, libnss_hesiod-2.23.so, libnss_hesiod.so.2,
libnss_nis-2.23.so, libnss_nisplus-2.23.so, libnss_nisplus.so.2, libnss_nis.so.2, libntfs-3g.so.861, libntfs-3g.so.861.0.0,
libpamc.so.0, libpamc.so.0.82.1, libpam_misc.so.0, libpam_misc.so.0.82.0, libpam.so.0, libpam.so.0.83.1, libparted.so.2,
libparted.so.2.0.1, libpci.so.3, libpci.so.3.3.1, libpcprofile.so, libpcre.so.3, libpcre.so.3.13.2, libply-boot-client.so.4,
libply-boot-client.so.4.0.0, libply.so.4, libply.so.4.0.0, libply-splash-core.so.4, libply-splash-core.so.4.0.0,
libply-splash-graphics.so.4, libply-splash-graphics.so.4.0.0, libpng12.so.0, libpng12.so.0.54.0, libpopt.so.0, libpopt.so.0.0.0,
libprocps.so.4, libprocps.so.4.0.0, libpthread-2.23.so, libpthread.so.0, libreadline.so.5, libreadline.so.5.2, libreadline.so.6,
libreadline.so.6.3, libresolv-2.23.so, libresolv.so.2, librt-2.23.so, librt.so.1, libseccomp.so.2, libseccomp.so.2.2.3, libSegFault.so,
libselinux.so.1, libsepol.so.1, libslang.so.2, libslang.so.2.3.0, libsmartcols.so.1, libsmartcols.so.1.1.0, libssl.so.1.0.0,
libss.so.2, libss.so.2.0, libsystemd.so.0, libsystemd.so.0.14.0, libthread_db-1.0.so, libthread_db.so.1, libtinfo.so.5,
libtinfo.so.5.9, libudev.so.1, libudev.so.1.6.4, libulockmgr.so.1, libulockmgr.so.1.0.1, libusb-0.1.so.4, libusb-0.1.so.4.4.4,
libusb-1.0.so.0, libusb-1.0.so.0.1.0, libutil-2.23.so, libutil.so.1, libuuid.so.1, libuuid.so.1.3.0, libwrap.so.0, libwrap.so.0.7.6,
libxtables.so.11, libxtables.so.11.0.0, libz.so.1, libz.so.1.2.8, security
View Code

细心的你可能会发现,在/etc目录下还存在一个名叫ld.so.cache的文件。从名字来看,估计和动态链接库缓存有关。的确,为了使得动态链接库可以被系统使用,当我们修改了/etc/ld.so.conf或/etc/ld.so.conf.d/目录下的任何文件,或者往那些目录下拷贝了新的动态链接库文件时,都需要运行一个很重要的命令:ldconfig,该命令位于/sbin目录下,主要的用途就是负责搜索/lib和/usr/lib,以及配置文件/etc/ld.so.conf里所列的目录下搜索可用的动态链接库文件,然后创建出动态加载程序/lib/ld-linux.so.2所需要的链接和(默认)缓存文件/etc/ld.so.cache(此文件里保存着已经排好序的动态链接库名字列表)。

也就是说:当用户在某个目录下面创建或拷贝了一个动态链接库,若想使其被系统共享,可以执行一下"ldconfig目录名"这个命令。此命令的功能在于让ldconfig将指定目录下的动态链接库被系统共享起来,即:在缓存文件/etc/ld.so.cache中追加进指定目录下的共享库。请注意:如果此目录不在/lib,/usr/lib及/etc/ld.so.conf文件所列的目录里面,则再次单独运行ldconfig时,此目录下的动态链接库可能不被系统共享了。单独运行ldconfig时,它只会搜索/lib、/usr/lib以及在/etc/ld.so.conf文件里所列的目录,用它们来重建/etc/ld.so.cache。

因此,对于我们自己开发的共享库可以将其拷贝到/lib、/etc/lib目录里,或者修改/etc/ld.so.conf文件将我们自己的库路径添加到该文件中,再执行ldconfig命令。

动态库使用参考:Linux下动态库的制作与使用

ldd(List Dynamic Dependencies)

功能

列出可执行文件或共享库的依赖文件,这里的依赖指的是动态库

语法

ldd(选项)(参数)
选项

--version:打印指令版本号;
-v:Print all information, including, for example, symbol versioning information.

[root@localhost lib]# ldd -v  /usr/bin/ls 
    linux-vdso.so.1 =>  (0x00007ffc28747000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fa1d1a37000)
    libcap.so.2 => /lib64/libcap.so.2 (0x00007fa1d1832000)
    libacl.so.1 => /lib64/libacl.so.1 (0x00007fa1d1629000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fa1d125c000)
    libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fa1d0ffa000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007fa1d0df6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fa1d1c5e000)
    libattr.so.1 => /lib64/libattr.so.1 (0x00007fa1d0bf1000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa1d09d5000)

    Version information:
    /usr/bin/ls:
        libacl.so.1 (ACL_1.0) => /lib64/libacl.so.1
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.17) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
    /lib64/libselinux.so.1:
        libdl.so.2 (GLIBC_2.2.5) => /lib64/libdl.so.2
        ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.8) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.7) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
    /lib64/libcap.so.2:
        libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.8) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        libattr.so.1 (ATTR_1.0) => /lib64/libattr.so.1
    /lib64/libacl.so.1:
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        libattr.so.1 (ATTR_1.0) => /lib64/libattr.so.1
    /lib64/libc.so.6:
        ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
    /lib64/libpcre.so.1:
        libpthread.so.0 (GLIBC_2.2.5) => /lib64/libpthread.so.0
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3) => /lib64/libc.so.6
    /lib64/libdl.so.2:
        ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
        libc.so.6 (GLIBC_PRIVATE) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
    /lib64/libattr.so.1:
        libc.so.6 (GLIBC_2.4) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
    /lib64/libpthread.so.0:
        ld-linux-x86-64.so.2 (GLIBC_2.2.5) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2
        ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
        libc.so.6 (GLIBC_2.14) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.3.2) => /lib64/libc.so.6
        libc.so.6 (GLIBC_PRIVATE) => /lib64/libc.so.6
        libc.so.6 (GLIBC_2.2.5) => /lib64/libc.so.6
View Code

-u:Print unused direct dependencies.  (Since glibc 2.3.4.)

[root@localhost lib]# ldd -u  /usr/bin/ls 
Unused direct dependencies:
    /lib64/libselinux.so.1
    /lib64/libcap.so.2
    /lib64/libacl.so.1
View Code

-d:Perform relocations and report any missing objects (ELF only).

[root@localhost lib]# ldd -d  /usr/bin/ls 
    linux-vdso.so.1 =>  (0x00007ffd88755000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f284ddcd000)
    libcap.so.2 => /lib64/libcap.so.2 (0x00007f284dbc8000)
    libacl.so.1 => /lib64/libacl.so.1 (0x00007f284d9bf000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f284d5f2000)
    libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f284d390000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f284d18c000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f284dff4000)
    libattr.so.1 => /lib64/libattr.so.1 (0x00007f284cf87000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f284cd6b000)
View Code

-r:Perform relocations for both data objects and functions, and report any missing objects or functions (ELF only).

[root@localhost lib]# ldd -r  /usr/bin/ls 
    linux-vdso.so.1 =>  (0x00007fff60bf9000)
    libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fd8560df000)
    libcap.so.2 => /lib64/libcap.so.2 (0x00007fd855eda000)
    libacl.so.1 => /lib64/libacl.so.1 (0x00007fd855cd1000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fd855904000)
    libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fd8556a2000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007fd85549e000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fd856306000)
    libattr.so.1 => /lib64/libattr.so.1 (0x00007fd855299000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fd85507d000)
View Code

--help:显示帮助信息。

参数

文件:指定可执行程序或者文库。

使用

最简单粗暴的使用方式,不带任何参数

查看共享库的依赖文件

root@ubuntu:/usr/lib# file libevent_openssl.so
libevent_openssl.so: symbolic link to libevent_openssl-2.1.so.6.0.2
root@ubuntu:/usr/lib# ldd libevent_openssl.so
    linux-vdso.so.1 =>  (0x00007fffeb79d000)
    libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f65cb531000)
    libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f65cb0ed000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f65caed0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f65cab05000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f65ca901000)
    /lib64/ld-linux-x86-64.so.2 (0x000055a2680a3000)
root@ubuntu:/usr/lib# ldd libevent_openssl-2.1.so.6.0.2
    linux-vdso.so.1 =>  (0x00007ffe80873000)
    libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f9e350a1000)
    libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f9e34c5d000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9e34a40000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9e34675000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9e34471000)
    /lib64/ld-linux-x86-64.so.2 (0x000055d3f064b000)
View Code

查看可执行文件的依赖文件

root@ubuntu:/DNXY/projects/dnxy_bike/src# file brks 
brks: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9d70993a3c150c156164b1bd88927f27651987e5, not stripped
root@ubuntu:/DNXY/projects/dnxy_bike/src# ldd brks 
    linux-vdso.so.1 =>  (0x00007ffecf0d9000)
    liblog4cpp.so.5 => ../third/lib/log4cpp/liblog4cpp.so.5 (0x00007fc23c150000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc23bf29000)
    libjsoncpp.so => ../third/lib/log4cpp/libjsoncpp.so (0x00007fc23bcdf000)
    libcurl.so.4 => ../third/lib/log4cpp/libcurl.so.4 (0x00007fc23ba7f000)
    libthrift-0.11.0.so => /usr/local/lib/libthrift-0.11.0.so (0x00007fc23b7b8000)
    libthriftnb-0.11.0.so => /usr/local/lib/libthriftnb-0.11.0.so (0x00007fc23b597000)
    libevent-2.1.so.6 => ../third/lib/log4cpp/libevent-2.1.so.6 (0x00007fc23b341000)
    libmysqlclient.so.20 => /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20 (0x00007fc23ad30000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fc23a9ad000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc23a6a4000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc23a48e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc23a0c3000)
    /lib64/ld-linux-x86-64.so.2 (0x000055f814b36000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc239ea9000)
    libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007fc239c40000)
    libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007fc2397fb000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc2395f7000)
View Code

不可以查看静态库的依赖文件

root@ubuntu:/usr/lib# ldd libcurl.a
    not a dynamic executable
View Code

查看静态库的依赖文件(说依赖不太恰当,应该是包含)。参考:Linux命令——ar

root@ubuntu:/usr/lib# ar -t libcurl.a
libcurl_la-file.o
libcurl_la-timeval.o
libcurl_la-base64.o
libcurl_la-hostip.o
libcurl_la-progress.o
libcurl_la-formdata.o
libcurl_la-cookie.o
libcurl_la-http.o
libcurl_la-sendf.o
libcurl_la-ftp.o
libcurl_la-url.o
libcurl_la-dict.o
libcurl_la-if2ip.o
libcurl_la-speedcheck.o
libcurl_la-ldap.o
libcurl_la-version.o
libcurl_la-getenv.o
libcurl_la-escape.o
libcurl_la-mprintf.o
libcurl_la-telnet.o
libcurl_la-netrc.o
libcurl_la-getinfo.o
libcurl_la-transfer.o
libcurl_la-strcase.o
libcurl_la-easy.o
libcurl_la-security.o
libcurl_la-curl_fnmatch.o
libcurl_la-fileinfo.o
libcurl_la-ftplistparser.o
libcurl_la-wildcard.o
libcurl_la-krb5.o
libcurl_la-memdebug.o
libcurl_la-http_chunks.o
libcurl_la-strtok.o
libcurl_la-connect.o
libcurl_la-llist.o
libcurl_la-hash.o
libcurl_la-multi.o
libcurl_la-content_encoding.o
libcurl_la-share.o
libcurl_la-http_digest.o
libcurl_la-md4.o
libcurl_la-md5.o
libcurl_la-http_negotiate.o
libcurl_la-inet_pton.o
libcurl_la-strtoofft.o
libcurl_la-strerror.o
libcurl_la-amigaos.o
libcurl_la-hostasyn.o
libcurl_la-hostip4.o
libcurl_la-hostip6.o
libcurl_la-hostsyn.o
libcurl_la-inet_ntop.o
libcurl_la-parsedate.o
libcurl_la-select.o
libcurl_la-tftp.o
libcurl_la-splay.o
libcurl_la-strdup.o
libcurl_la-socks.o
libcurl_la-ssh.o
libcurl_la-ssh-libssh.o
libcurl_la-curl_addrinfo.o
libcurl_la-socks_gssapi.o
libcurl_la-socks_sspi.o
libcurl_la-curl_sspi.o
libcurl_la-slist.o
libcurl_la-nonblock.o
libcurl_la-curl_memrchr.o
libcurl_la-imap.o
libcurl_la-pop3.o
libcurl_la-smtp.o
libcurl_la-pingpong.o
libcurl_la-rtsp.o
libcurl_la-curl_threads.o
libcurl_la-warnless.o
libcurl_la-hmac.o
libcurl_la-curl_rtmp.o
libcurl_la-openldap.o
libcurl_la-curl_gethostname.o
libcurl_la-gopher.o
libcurl_la-idn_win32.o
libcurl_la-http_proxy.o
libcurl_la-non-ascii.o
libcurl_la-asyn-ares.o
libcurl_la-asyn-thread.o
libcurl_la-curl_gssapi.o
libcurl_la-http_ntlm.o
libcurl_la-curl_ntlm_wb.o
libcurl_la-curl_ntlm_core.o
libcurl_la-curl_sasl.o
libcurl_la-rand.o
libcurl_la-curl_multibyte.o
libcurl_la-hostcheck.o
libcurl_la-conncache.o
libcurl_la-pipeline.o
libcurl_la-dotdot.o
libcurl_la-x509asn1.o
libcurl_la-http2.o
libcurl_la-smb.o
libcurl_la-curl_endian.o
libcurl_la-curl_des.o
libcurl_la-system_win32.o
libcurl_la-mime.o
libcurl_la-sha256.o
libcurl_la-setopt.o
libcurl_la-curl_path.o
libcurl_la-curl_ctype.o
libcurl_la-curl_range.o
libcurl_la-psl.o
libcurl_la-vauth.o
libcurl_la-cleartext.o
libcurl_la-cram.o
libcurl_la-digest.o
libcurl_la-digest_sspi.o
libcurl_la-krb5_gssapi.o
libcurl_la-krb5_sspi.o
libcurl_la-ntlm.o
libcurl_la-ntlm_sspi.o
libcurl_la-oauth2.o
libcurl_la-spnego_gssapi.o
libcurl_la-spnego_sspi.o
libcurl_la-openssl.o
libcurl_la-gtls.o
libcurl_la-vtls.o
libcurl_la-nss.o
libcurl_la-polarssl.o
libcurl_la-polarssl_threadlock.o
libcurl_la-axtls.o
libcurl_la-cyassl.o
libcurl_la-schannel.o
libcurl_la-schannel_verify.o
libcurl_la-darwinssl.o
libcurl_la-gskit.o
libcurl_la-mbedtls.o
View Code

在 ldd 命令打印的结果中,“=>”左边的表示该程序需要连接的共享库之 so 名称,右边表示由 Linux 系统找到的对应共享库在文件系统中的具体位置。默认情况下,/etc/ld.so.conf 文件中包含有默认的共享库搜索路径。

一个更好的替代

ldd本质上是一个脚本,并不是一个ELF格式的可执行文件。file使用

root@ubuntu:/# file /usr/bin/ldd
/usr/bin/ldd: Bourne-Again shell script, ASCII text executable
View Code

ldd能够显示可执行模块的dependency,其原理是通过设置一系列的环境变量,如下:LD_TRACE_LOADED_OBJECTS、LD_WARN、LD_BIND_NOW、LD_LIBRARY_VERSION、LD_VERBOSE等。当LD_TRACE_LOADED_OBJECTS环境变量不为空时,任何可执行程序在运行时,它都会只显示模块的dependency,而程序并不真正执行。要不你可以在shell终端测试一下,如下:

export LD_TRACE_LOADED_OBJECTS=1

root@ubuntu:/usr/lib# export LD_TRACE_LOADED_OBJECTS=1
root@ubuntu:/usr/lib# ls
    linux-vdso.so.1 =>  (0x00007ffcd59fe000)
    libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f775f7f6000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f775f42c000)
    libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x00007f775f1bc000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f775efb8000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f775fa18000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f775ed9b000)
root@ubuntu:/usr/lib# unset LD_TRACE_LOADED_OBJECTS
root@ubuntu:/usr/lib# ls
accountsservice                libevent_openssl.so                libopen-pal.so
apt                            libevent_pthreads-2.1.so.6         libopen-pal.so.13
binfmt.d                       libevent_pthreads-2.1.so.6.0.2     libopen-pal.so.13.0.2
byobu                          libevent_pthreads.a                libopen-rte.so
command-not-found              libevent_pthreads.la               libopen-rte.so.12
compat-ld                      libevent_pthreads.so               libopen-rte.so.12.0.2
dbus-1.0                       libevent.so                        liboshmem.so
dpkg                           libguestlib.so.0                   libtinyxml.a
dracut                         libguestlib.so.0.0.0               libvmtools.so.0
eject                          libhgfs.so.0                       libvmtools.so.0.0.0
emacsen-common                 libhgfs.so.0.0.0                   linux-boot-probes
gcc                            libibverbs.a                       locale
git-core                       libibverbs.so                      lxcfs
gnupg                          libibverbs.so.1                    lxd
gold-ld                        libibverbs.so.1.0.0                man-db
groff                          libjsoncpp.a                       mime
grub                           libjsoncpp.so                      modules-load.d
grub-legacy                    libjson_linux-gcc-5.4.0_libmt.a    mysql
initcpio                       libjson_linux-gcc-5.4.0_libmt.so   openmpi
initramfs-tools                liblog4cpp.a                       openssh
insserv                        liblog4cpp.la                      open-vm-tools
klibc                          liblog4cpp.so                      os-prober
language-selector              liblog4cpp.so.5                    os-probes
ldscripts                      liblog4cpp.so.5.0.6                os-release
libcurl.a                      libmca_common_sm.so                perl5
libcurl.la                     libmca_common_sm.so.4              pkgconfig
libcurl.so                     libmca_common_sm.so.4.0.4          pkg-config.multiarch
libcurl.so.4                   libmca_common_verbs.so             pm-utils
libcurl.so.4.5.0               libmca_common_verbs.so.7           policykit-1
libDeployPkg.so.0              libmca_common_verbs.so.7.0.0       python2.7
libDeployPkg.so.0.0.0          libmpi_cxx.so                      python3
libevent-2.1.so.6              libmpi_cxx.so.1                    python3.5
libevent-2.1.so.6.0.2          libmpi_cxx.so.1.1.3                rsyslog
libevent.a                     libmpi_mpifh.so                    sasl2
libevent_core-2.1.so.6         libmpi_mpifh.so.12                 scons
libevent_core-2.1.so.6.0.2     libmpi_mpifh.so.12.0.0             sftp-server
libevent_core.a                libmpi.so                          snapd
libevent_core.la               libmpi++.so                        software-properties
libevent_core.so               libmpi.so.12                       ssl
libevent_extra-2.1.so.6        libmpi.so.12.0.2                   sudo
libevent_extra-2.1.so.6.0.2    libmpi_usempif08.so                systemd
libevent_extra.a               libmpi_usempif08.so.11             tar
libevent_extra.la              libmpi_usempif08.so.11.1.0         tasksel
libevent_extra.so              libmpi_usempi_ignore_tkr.so        tc
libevent.la                    libmpi_usempi_ignore_tkr.so.6      tmpfiles.d
libevent_openssl-2.1.so.6      libmpi_usempi_ignore_tkr.so.6.1.0  ubuntu-release-upgrader
libevent_openssl-2.1.so.6.0.2  libompitrace.so                    update-notifier
libevent_openssl.a             libompitrace.so.0                  valgrind
libevent_openssl.la            libompitrace.so.0.0.0              x86_64-linux-gnu
View Code

ldd显示可执行模块的dependency的工作原理,其实质是通过ld-linux.so(elf动态库的装载器)来实现的。我们知道,ld-linux.so模块会先于executable模块程序工作,并获得控制权,因此当上述的那些环境变量被设置时,ld-linux.so选择了显示可执行模块的dependency。

实际上可以直接执行ld-linux.so模块,如:/lib/ld-linux.so.2 --list program(这相当于ldd program)

某些环境下,某些ldd版本可能会试图执行ldd参数中对应的程序。因此对于那些不受信任的可执行文件或动态库请不要使用ldd,因为有更好的替代方案

objdump -p /path/to/program | grep NEEDED

root@ubuntu:/DNXY/projects/dnxy_bike/src# objdump -p brks | grep NEEDED
  NEEDED               liblog4cpp.so.5
  NEEDED               libpthread.so.0
  NEEDED               libjsoncpp.so
  NEEDED               libcurl.so.4
  NEEDED               libthrift-0.11.0.so
  NEEDED               libthriftnb-0.11.0.so
  NEEDED               libevent-2.1.so.6
  NEEDED               libmysqlclient.so.20
  NEEDED               libstdc++.so.6
  NEEDED               libm.so.6
  NEEDED               libgcc_s.so.1
  NEEDED               libc.so.6
root@ubuntu:/DNXY/projects/dnxy_bike/src# ldd brks 
    linux-vdso.so.1 =>  (0x00007fff36d70000)
    liblog4cpp.so.5 => ../third/lib/log4cpp/liblog4cpp.so.5 (0x00007ffb5bf49000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007ffb5bd22000)
    libjsoncpp.so => ../third/lib/log4cpp/libjsoncpp.so (0x00007ffb5bad8000)
    libcurl.so.4 => ../third/lib/log4cpp/libcurl.so.4 (0x00007ffb5b878000)
    libthrift-0.11.0.so => /usr/local/lib/libthrift-0.11.0.so (0x00007ffb5b5b1000)
    libthriftnb-0.11.0.so => /usr/local/lib/libthriftnb-0.11.0.so (0x00007ffb5b390000)
    libevent-2.1.so.6 => ../third/lib/log4cpp/libevent-2.1.so.6 (0x00007ffb5b13a000)
    libmysqlclient.so.20 => /usr/lib/x86_64-linux-gnu/libmysqlclient.so.20 (0x00007ffb5ab29000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007ffb5a7a6000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007ffb5a49d000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007ffb5a287000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ffb59ebc000)
    /lib64/ld-linux-x86-64.so.2 (0x0000559ef684b000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007ffb59ca2000)
    libssl.so.1.0.0 => /lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007ffb59a39000)
    libcrypto.so.1.0.0 => /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007ffb595f4000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007ffb593f0000)
View Code

但是从输出结果看,objdump比ldd输出的依赖少了点。

ldconfig

功能

配置动态链接器运行时绑定(configure dynamic linker run-time bindings)

说明

对命令行指定的目录,文件/etc/ld.so.conf中指定的目录,/usr/lib和/lib等受新任的目录下面找到的最新共享库,ldconfig为他们创建必要的链接和缓存。链接和缓存给动态链接器ld.so使用。在确定哪些版本的链接应更新时,ldconfig会检查它遇到的库的头和文件名。 扫描库时,ldconfig忽略符号链接。

当任何库被连接的时候,ldconfig将尝试根据C库来推断ELF库的类型(eg:libc 5.x或libc 6.x(glibc))。因此在制作动态库时,明智的做法使用参数-lc显式连接到libc。 ldconfig能够将多个ABI类型的库存储单个缓存中,这些缓存允许本地运行多个ABI,如ia32 / ia64 / x86_64或sparc32 / sparc64。

现有的某些库没有包含足够的信息用于推导他们的类型,因此/etc/ld.so.conf文件格式允许指定期望的类型。但这仅限于对ELF类型,格式类似于“dirname = TYPE”,其中type可以是libc4,libc5或libc6。(此语法也适用于命令行)。不允许有空格。

包含=的目录名称不再合法,除非它们也具有预期的类型说明符。

通常情况下,ldconfig以root身份运行运行,因为它可能需要对某些目录和文件有root的写入权限。 如果使用-r选项更改根目录,只要您对该目录树有足够的权限,可以不必是root用户。

语法

ldconfig [OPTION...]

选项

-v --verbose

详细模式。在扫描动态库时,会显示动态库当前版本号,库在那个目录下,以及指向该库的链接。

root@ubuntu:~# ldconfig -v
...
/usr/lib/x86_64-linux-gnu/libfakeroot:
    libfakeroot-0.so -> libfakeroot-tcp.so
/usr/local/lib:
    libluasocket.so.0 -> libluasocket.so.0.0.0
    libthrift-0.11.0.so -> libthrift.so
    libthriftz-0.11.0.so -> libthriftz.so
    libluabitwise.so.0 -> libluabitwise.so.0.0.0
    libthrift_c_glib.so.0 -> libthrift_c_glib.so.0.0.0
    liblua.so -> liblua.so
    libthriftnb-0.11.0.so -> libthriftnb.so
    libluabpack.so.0 -> libluabpack.so.0.0.0
    liblualongnumber.so.0 -> liblualongnumber.so.0.0.0
...
View Code

->前面是后面的符号链接

-n 

ldconfig仅扫描命令行指定下的目录,不扫描受信目录(/lib,/usr/lib)和配置文件/etc/ld.so.conf指定的目录。

-N

ldconfig不重建缓存文件(/etc/ld.so.cache),但是还会跟新文件的链接。除非指定-X

-X

ldconfig不更新文件的连接,但是还会重建缓存文件(/etc/ld.so.cache)。除非指定-N

-f conf

使用conf文件,而不是默认的/etc/ld.so.conf

-C cache

Use cache instead of /etc/ld.so.cache.

-r root

此选项改变应用程序的根目录为ROOT(是调用chroot函数实现的).选择此项时,系统默认的配置文件/etc/ld.so.conf,实际对应的为ROOT/etc/ld.so.conf.如用-r/usr/zzz时,打开配置文件/etc/ld.so.conf时,实际打开的是/usr/zzz/etc/ld.so.conf文件.用此选项,可以大大增加动态链接库管理的灵活性.

-l

通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接.选择此项时,将进入专家模式,需要手工设置连接.一般用户不用此项.

-p 或 --print-cache

此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字。

-c FORMAT 或--format=FORMAT

此选项用于指定缓存文件所使用的格式,共有三种:ld(老格式),new(新格式)和compat(兼容格式,此为默认格式)。

-V 

此选项打印出ldconfig的版本信息,而后退出.

--help 或--usage 

这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出。

ldconfig需要注意的地方

  1. 往/lib和/usr/lib里面加东西,是不用修改/etc/ld.so.conf文件的,但是添加完后需要调用下ldconfig,不然添加的library会找不到。
  2. 如果添加的library不在/lib和/usr/lib里面的话,就一定要修改/etc/ld.so.conf文件,往该文件追加library所在的路径,然后也需要重新调用下ldconfig命令。比如在安装MySQL的时候,其库文件/usr/local/mysql/lib,就需要追加到/etc/ld.so.conf文件中。命令如下:

                 # echo "/usr/local/mysql/lib" >> /etc/ld.so.conf

                 # ldconfig -v | grep mysql

  3. 如果添加的library不在/lib或/usr/lib下,但是却没有权限操作写/etc/ld.so.conf文件的话,这时就需要往export里写一个全局变量LD_LIBRARY_PATH,就可以了。但是这种方法有个缺点,就是环境变量都是局部于进程的,也就是说你在一个shell终端export LD_LIBRARY_PATH,可以找到动态库。但是当shell终端关闭再打开的时候还是会报找不到动态库。这是和可以把export LD_LIBRARY_PATH写在.bashrc里面,这样只要一执行shell就能找到动态库。
  4. 除了export LD_LIBRARY_PATH方法外,把我们自己 写的动态库手动拷贝到/lib目录下也可以。/lib是系统动态链接库所在位置。一般不使用这种方法。

一个很好的中文在线man手册

Linux命令大全

最后说明最开始的那个问题是怎么解决的

其实就是执行了一遍ldconfig命令,命令虽简单,但是背后原理深刻,理解很重要。

 

 

 

posted @ 2018-10-17 23:58  克拉默与矩阵  阅读(1135)  评论(0编辑  收藏  举报