Shared Libraries Manage |
动态库是从程序外部加载的,未在编译时集成到程序自身当中。
情形:
error while loading shared libraries
Linux中的.so文件类似于Windows中的DLL,是动态链接库,也有人译作共享库(因so的全称为Shared Object)。当多个程序使用同一个动态链接库时,既能节约可执行文件的大小,也能减少运行时的内存占用。
Linux中绝大多数.so文件都存放在/lib64
、/usr/lib64/
,对于64位和32位共存的系统,32位的动态库可能会放在/lib32
、/usr/lib32
,完整的动态库存放路径列表可通过/etc/ld.so.conf文件配置。(如果修改了配置,需要用 /sbin/ldconfig 命令更新缓存)
应注意动态库搜寻路径并不包括当前文件夹,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到so的问题,如
xxxxxxxxxx
1./nginx: error while loading shared libraries: libnss3.so.1d: cannot open shared object file: No such file or directory
此时可用LD_LIBRARY_PATH环境变量做临时设置,如:
xxxxxxxxxx
11LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH ./chrome
也有些so文件是在程序执行时临时加载的(如插件),它们的路径就比较灵活,只要可执行文件能找到它就行了。
动态库的版本总是个问题,如果编译时链接的库和执行时提供的不一样,难免会导致程序的执行发生诡异的错误。为解决此问题,Linux系列的做法是这样的:
首先,每个so文件有一个文件名,如libABC.so.x.y.z,这里ABC是库名称,x.y.z是文件的版本号,一般来说:
在系统中,会存在一些符号链接, 如:
xxxxxxxxxx
21libpam.so -> libpam.so.0.83.0
2libpam.so.0 -> libpam.so.0.83.0
其中第一个主要在使用该库开发其它程序时使用,比如gcc想连接PAM库,直接连libpam.so就行了,不必在链接时给出它的具体版本。第二个则主要用在运行时,因为前面说了第一位版本一样的库是互相兼容的,所以程序运行时只要试图连接libpam.so.0就够了,不必在意其具体的版本。ldconfig可以自动生成这些链接。
那么编译程序时gcc在链接一个so文件(如libpam.so)时,如何知道该程序运行时链接哪个文件呢(上例中是libpam.so.0)?原来产生so文件时,可以指定一个soname,一般形如libABC.so.x。人们编译可执行文件时,如果链接了某个so,存在可执行文件里的.so文件名并不是其全名,而是这个soname。比如上例中,这个soname就是libpam.so.0。回头看一下上节ldd的结果,可以印证这一现象。
有时还会看到形如libABCn.so,即版本号出现在.so前面的库文件,如libXaw6.so。此类文件一般是为开发者着想,比如GTK+ 3已经推出,但很多开发者还是想用GTK+ 2开发软件。由于编译时只连接无版本号的.so文件,就只有把版本号放在.so前面了。
查询程序本身是否有外部的动态库依赖
在windows上默认安装时没有专门的命令或工具,可通过 dumpbin.exe
(需要安装了vs studio之后,它提供此)或其它第3方工具,比如 Dependencies
1,此处以它为示例说明:
以mysqld.exe安装程序为例将其拖入主程序界面,即显示依赖列表:由于在当前的系统中缺少vcdist可以发现mysqld.exe在5.7版本时显示缺少MSVCR120/MSVCP120,此时程序执行会报错。而这2个dll是在[Microsoft Visual C++ Redistributable Packages for Visual Studio 2012中提供的,需要分别安装。而,另一个情况:发现mysqld.exe在8.0版本时显示依赖正常,表示在在当前的系统依赖已经存在,满足程序执行的依赖环境。
安装依赖或从其它OS中直接提取将C:\Windows\System32\MSVCR120.dll
、C:\Windows\System32\MSVCP120.dll
放到当前系统同样路径下,刷新Dependencies界面,即可看到依赖依赖问题处理掉了。(注意:有些情况下,可能系统通过其它的环境变量将依赖处理掉了,但Dependencies程序可能只搜索并显示了位于C:\Windows\System32\
下面的,最终结果是以程序执行不报错为准。)
另,如下图:当前系统win11中检测mysqld.exe v8.0.21则无依赖问题,表明最新的系统环境满足依赖条件。这里体现了操作系统发行版与应用程序的兼容性一致。同时期的操作系统和应用往往是开发者优先测试的。
linux系统中可以使用ldd命令查看,比如ldd在rhel系列分支系统中在glibc-common软件包中提供的,是默认安装了的,ldd命令可以直接使用。
xxxxxxxxxx
81[root ]# yum provides ldd
2Loaded plugins: fastestmirror, getpagespeed
3Loading mirror speeds from cached hostfile
4glibc-common-2.17-317.el7.x86_64 : Common binaries and locale data for glibc
5Repo : base
6Matched from:
7Filename : /usr/bin/ldd
8
xxxxxxxxxx
851[root ]# /usr/local/nginxfrontend/nginxfrontend -t
2/usr/local/nginxfrontend/nginxfrontend: error while loading shared libraries: libgd.so.3: cannot open shared object file: No such file or directory
3[root ]# ldd /usr/local/nginxfrontend/nginxfrontend
4 linux-vdso.so.1 => (0x00007ffc8271d000)
5 libdl.so.2 => /lib64/libdl.so.2 (0x00007f8be4d02000)
6 libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8be4ae6000)
7 libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f8be48af000)
8 libmaxminddb.so.0 => /lib64/libmaxminddb.so.0 (0x00007f8be46a9000)
9 libsregex.so.0 => /lib64/libsregex.so.0 (0x00007f8be449c000)
10 libm.so.6 => /lib64/libm.so.6 (0x00007f8be419a000)
11 libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f8be3e30000)
12 libxslt.so.1 => /lib64/libxslt.so.1 (0x00007f8be3bf1000)
13 libexslt.so.0 => /lib64/libexslt.so.0 (0x00007f8be39dc000)
14 libgd.so.3 => not found
15 libprofiler.so.0 => /lib64/libprofiler.so.0 (0x00007f8be37c8000)
16 libc.so.6 => /lib64/libc.so.6 (0x00007f8be33fa000)
17 /lib64/ld-linux-x86-64.so.2 (0x00007f8be4f06000)
18 libfreebl3.so => /lib64/libfreebl3.so (0x00007f8be31f7000)
19 libz.so.1 => /lib64/libz.so.1 (0x00007f8be2fe1000)
20 liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f8be2dbb000)
21 libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007f8be2b3a000)
22 libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f8be2935000)
23 libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f8be262d000)
24 libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f8be2417000)
25[root ]# find / -name "libgd.so*"
26/usr/lib64/libgd.so.2
27/usr/lib64/libgd.so.103.0.11
28/usr/lib64/libgd.so
29/usr/lib64/libgd.so.103
30/usr/lib64/libgd.so.2.0.0
31/usr/local/lib/libgd.so.3.0.8
32/usr/local/lib/libgd.so.3
33/usr/local/lib/libgd.so
34/opt/nginx_build_dir/libgd-2.3.0/src/.libs/libgd.so.3.0.8
35/opt/nginx_build_dir/libgd-2.3.0/src/.libs/libgd.so.3
36/opt/nginx_build_dir/libgd-2.3.0/src/.libs/libgd.so
37
38# 可以看出这个库是nginx编译过程中引入实时编译的,需要重建关联到系统环境变量中。
39
40[root ]# ln -s /usr/local/lib/libgd.so.3 /lib64/
41[root ]# ldd /usr/local/nginxfrontend/nginxfrontend
42 linux-vdso.so.1 => (0x00007fffdf5f5000)
43 libdl.so.2 => /lib64/libdl.so.2 (0x00007f5250f08000)
44 libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f5250cec000)
45 libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007f5250ab5000)
46 libmaxminddb.so.0 => /lib64/libmaxminddb.so.0 (0x00007f52508af000)
47 libsregex.so.0 => /lib64/libsregex.so.0 (0x00007f52506a2000)
48 libm.so.6 => /lib64/libm.so.6 (0x00007f52503a0000)
49 libxml2.so.2 => /lib64/libxml2.so.2 (0x00007f5250036000)
50 libxslt.so.1 => /lib64/libxslt.so.1 (0x00007f524fdf7000)
51 libexslt.so.0 => /lib64/libexslt.so.0 (0x00007f524fbe2000)
52 libgd.so.3 => /lib64/libgd.so.3 (0x00007f524f97a000)
53 libprofiler.so.0 => /lib64/libprofiler.so.0 (0x00007f524f766000)
54 libc.so.6 => /lib64/libc.so.6 (0x00007f524f398000)
55 /lib64/ld-linux-x86-64.so.2 (0x00007f525110c000)
56 libfreebl3.so => /lib64/libfreebl3.so (0x00007f524f195000)
57 libz.so.1 => /lib64/libz.so.1 (0x00007f524ef7f000)
58 liblzma.so.5 => /lib64/liblzma.so.5 (0x00007f524ed59000)
59 libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007f524ead8000)
60 libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007f524e8d3000)
61 libpng15.so.15 => /lib64/libpng15.so.15 (0x00007f524e6a8000)
62 libfontconfig.so.1 => /lib64/libfontconfig.so.1 (0x00007f524e466000)
63 libfreetype.so.6 => /lib64/libfreetype.so.6 (0x00007f524e1a7000)
64 libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007f524df52000)
65 libimagequant.so.0 => /lib/libimagequant.so.0 (0x00007f524dd3f000)
66 libXpm.so.4 => /lib64/libXpm.so.4 (0x00007f524db2d000)
67 libX11.so.6 => /lib64/libX11.so.6 (0x00007f524d7ef000)
68 libtiff.so.5 => /lib64/libtiff.so.5 (0x00007f524d57b000)
69 libwebp.so.7 => /lib64/libwebp.so.7 (0x00007f524d30b000)
70 libgomp.so.1 => /lib64/libgomp.so.1 (0x00007f524d0e5000)
71 libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f524cddd000)
72 libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f524cbc7000)
73 libexpat.so.1 => /lib64/libexpat.so.1 (0x00007f524c99d000)
74 libuuid.so.1 => /lib64/libuuid.so.1 (0x00007f524c798000)
75 libbz2.so.1 => /lib64/libbz2.so.1 (0x00007f524c588000)
76 libxcb.so.1 => /lib64/libxcb.so.1 (0x00007f524c360000)
77 libjbig.so.2.0 => /lib64/libjbig.so.2.0 (0x00007f524c154000)
78 libXau.so.6 => /lib64/libXau.so.6 (0x00007f524bf50000)
79[root ]#
80
81# 检查rpm软件包中的提供的so来源
82
83
84so的全称为Shared Object
85
xxxxxxxxxx
61[root ]# yum provides */libXpm.so.4
2libXpm-3.5.12-1.el7.i686 : X.Org X11 libXpm runtime library
3Repo : base
4Matched from:
5Filename : /usr/lib/libXpm.so.4
6
可在编译时指定路径,或将统计完成的文件进行移动。
为了区分开发编译中的类似命令,这里罗列部分。
ld.so或ld-linux.so是系统级的加载器或连接程序,它可以间接运行或直接运行。其中,间接运行是指被其它动态库或程序调用,此时,无参数可以跳过,而在ELF中一般存储在程序执行过程的.interp
章节中。
注:ELF可执行和可链接格式(Executable and Linkable Format,缩写为ELF),常被称为ELF格式,在计算机科学中,是一种用于执行档、目的档、共享库和核心转储的标准文件格式。
执行语法示例:
/lib/ld-linux.so.* [OPTIONS] [PROGRAM [ARGUMENTS]]
加载和动态链接 从编译/链接和运行的角度看,库分为动态链接和静态链接。相应的两种不同的ELF格式映像:
1)一种是静态链接的,在装入/启动其运行时无需装入函数库映像、也无需进行动态连接。
2)另一种是动态连接,需要在装入/启动其运行时同时装入函数库映像并进行动态链接。
Linux内核既支持静态链接的ELF映像,也支持动态链接的ELF映像,GNU规定:
1)把ELF映像的装入/启动入在Linux内核中;
2)把动态链接的实现放在用户空间(glibc),并为此提供一个称为”解释器”(ld-linux.so.2)的工具软件,而解释器的装入/启动也由内核负责。
通过LD_ASSUME_KERNEL设置Linux的线程实现模型 为了实现向后兼容,许多Linux发行版支持旧的LinuxThreads实现以及新的本地POSIX线程库(NPTL)。通过设置LD_ASSUME_KERNEL环境变量,动态链接器将假定它是运行在一个特定的内核版本上。这将覆盖程序在运行时,动态链接器默认选择的线程实现(通常是NPTL),而强行使用旧的LinuxThreads实现。
xxxxxxxxxx
1操作系统发展历史,许多32位Linux系统有3个独立的glibc版本,每个版本都指定其最低的操作系统的应用程序二进制接口(ABI),包括内核版本和所提供的线程实现模型。一般在如下三个目录:/lib/tls , /lib/i686 , /lib 。
/lib/tls/libc.so.6: 最低的ABI = 2.4.20 本机POSIX线程库(NPTL)
/lib/i686/libc.so.6: 最低的ABI = 2.4.1 标准的LinuxThreads,动态线程栈大小 /lib/libc.so.6
xxxxxxxxxx
81最低的ABI = 2.2.5
2早期的LinuxThreads,固定线程栈大小
3
4注意:64位系统不支持旧2.2.5 LinuxThreads实现。
5
6你可能通过下面的命令来确定你的系统所支持的各个glic库的线程实现模型:
7
8$ /lib/tls/libc.so.6 | grep [T|t]hreads
Native POSIX Threads Library by Ulrich Drepper $ /lib/i686/libc.so.6 | grep [T|t]hreads linuxthreads-0.10 by Xavier Leroy $ /lib/libc.so.6 | grep [T|t]hreads linuxthreads-0.10 by Xavier Leroy
x1动态库(共享库,*.so)可以告知动态链接器它能够正常运行所必需的最低的操作系统的应用程序二进制接口(ABI)版本。的你的程序运行时,动态链接器会根据最近的动态库查找路径并依次查找:/lib/tls , /lib/i686 , /lib。它会链接找到第一个满足最低ABI版本要求的库,或者无法找到满足最低ABI版本的库,链接失败并终止程序。
2
3设置LD_ASSUME_KERNEL低于任何glibc动态库版本的最低要求的ABI版本,这样链接器将跳过该glibc库,并尝试找到一个比该版本更旧的线程实现的glibc库。
4
5我们可以设置该环境变量,假定当前操作系统是一个特定的ABI /内核版本。这样可以达到跳过默认顺序链接的线实现 ,而使用特定版本库的线程实现。
6
7$ export LD_ASSUME_KERNEL=X.Y.Z
8
9注意:不要设置环境变量值为ABI低于2.2.5,这样会导致使用了动态链接库的程序无法正常运行。不过设置错误了也不用担心,你可以马上改回环境变量原来的值。
10
大多数程序并不关心底层的库是哪种实现,这样即便设置 LD_ASSUME_KERNEL变量也没作用。因为库的版本不同,但提供的API相同。但也有些应用程序因某些不符合规范的操作而需要使用LinuxThreads线程实现,NPTL线程实现会导致运行失败。这种情况下就可通过 LD_ASSUME_KERNEL环境变量实现动态链接器跳过NPTL库的目的。
ldd2是一个脚本,它是对/lib/ld-linux.so.2 /lib64/ld-linux-x86-64.so.2 /libx32/ld-linux-x32.so.2的封装。ldd脚本中有详细的说明注释信息。
而上面的库也不一定都存在,比如centos7.9中以/lib64/ld-linux-x86-64.so.2存在,你可以直接使用库来代替,如下:
xxxxxxxxxx
651[root ~]# /lib64/ld-linux-x86-64.so.2 --list /usr/local/nginxfrontend/nginxfrontend
2 linux-vdso.so.1 => (0x00007ffddd96e000)
3 libdl.so.2 => /lib64/libdl.so.2 (0x00007fe114d9a000)
4 libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe114b7e000)
5 libcrypt.so.1 => /lib64/libcrypt.so.1 (0x00007fe114947000)
6 libmaxminddb.so.0 => /lib64/libmaxminddb.so.0 (0x00007fe114741000)
7 libsregex.so.0 => /lib64/libsregex.so.0 (0x00007fe114534000)
8 libm.so.6 => /lib64/libm.so.6 (0x00007fe114232000)
9 libxml2.so.2 => /lib64/libxml2.so.2 (0x00007fe113ec8000)
10 libxslt.so.1 => /lib64/libxslt.so.1 (0x00007fe113c89000)
11 libexslt.so.0 => /lib64/libexslt.so.0 (0x00007fe113a74000)
12 libgd.so.3 => /lib64/libgd.so.3 (0x00007fe11380c000)
13 libprofiler.so.0 => /lib64/libprofiler.so.0 (0x00007fe1135f8000)
14 libc.so.6 => /lib64/libc.so.6 (0x00007fe11322a000)
15 /lib64/ld-linux-x86-64.so.2 (0x00007fe114f9e000)
16 libfreebl3.so => /lib64/libfreebl3.so (0x00007fe113027000)
17 libz.so.1 => /lib64/libz.so.1 (0x00007fe112e11000)
18 liblzma.so.5 => /lib64/liblzma.so.5 (0x00007fe112beb000)
19 libgcrypt.so.11 => /lib64/libgcrypt.so.11 (0x00007fe11296a000)
20 libgpg-error.so.0 => /lib64/libgpg-error.so.0 (0x00007fe112765000)
21 libpng15.so.15 => /lib64/libpng15.so.15 (0x00007fe11253a000)
22 libfontconfig.so.1 => /lib64/libfontconfig.so.1 (0x00007fe1122f8000)
23 libfreetype.so.6 => /lib64/libfreetype.so.6 (0x00007fe112039000)
24 libjpeg.so.62 => /lib64/libjpeg.so.62 (0x00007fe111de4000)
25 libimagequant.so.0 => /lib/libimagequant.so.0 (0x00007fe111bd1000)
26 libXpm.so.4 => /lib64/libXpm.so.4 (0x00007fe1119bf000)
27 libX11.so.6 => /lib64/libX11.so.6 (0x00007fe111681000)
28 libtiff.so.5 => /lib64/libtiff.so.5 (0x00007fe11140d000)
29 libwebp.so.7 => /lib64/libwebp.so.7 (0x00007fe11119d000)
30 libgomp.so.1 => /lib64/libgomp.so.1 (0x00007fe110f77000)
31 libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007fe110c6f000)
32 libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fe110a59000)
33 libexpat.so.1 => /lib64/libexpat.so.1 (0x00007fe11082f000)
34 libuuid.so.1 => /lib64/libuuid.so.1 (0x00007fe11062a000)
35 libbz2.so.1 => /lib64/libbz2.so.1 (0x00007fe11041a000)
36 libxcb.so.1 => /lib64/libxcb.so.1 (0x00007fe1101f2000)
37 libjbig.so.2.0 => /lib64/libjbig.so.2.0 (0x00007fe10ffe6000)
38 libXau.so.6 => /lib64/libXau.so.6 (0x00007fe10fde2000)
39[root ~]# /lib64/ld-linux-x86-64.so.2 --verify /usr/local/nginxfrontend/nginxfrontend
40
41[root ~]# /lib64/ld-linux-x86-64.so.2
42Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]
43You have invoked `ld.so', the helper program for shared library executables.
44This program usually lives in the file `/lib/ld.so', and special directives
45in executable files using ELF shared libraries tell the system's program
46loader to load the helper program from this file. This helper program loads
47the shared libraries needed by the program executable, prepares the program
48to run, and runs it. You may invoke this helper program directly from the
49command line to load and run an ELF executable file; this is like executing
50that file itself, but always uses this helper program from the file you
51specified, instead of the helper program file specified in the executable
52file you run. This is mostly of use for maintainers to test new versions
53of this helper program; chances are you did not intend to run this program.
54
55 --list list all dependencies and how they are resolved
56 --verify verify that given object really is a dynamically linked
57 object we can handle
58 --inhibit-cache Do not use /etc/ld.so.cache
59 --library-path PATH use given PATH instead of content of the environment
60 variable LD_LIBRARY_PATH
61 --inhibit-rpath LIST ignore RUNPATH and RPATH information in object names
62 in LIST
63 --audit LIST use objects named in LIST as auditors
64[root ~]#
65
注意:
ldd的标准版本与glibc2一起提供。Libc5与老版本以前提供,在一些系统中还存在。在libc5版本中长选项不支持。另一方面,glibc2版本不支持-V选项,只提供等价的--version选项。
如果命令行中给定的库名字包含'/',这个程序的libc5版本将使用它作为库名字;否则它将在标准位置搜索库。运行一个当前目录下的共享库,加前缀"./"。 错误: ldd不能工作在a.out格式的共享库上。 ldd不能工作在一些非常老的a.out程序上,这些程序在支持ldd的编译器发行前已经创建。如果你在这种类型的程序上使用ldd,程序将尝试argc = 0的运行方式,其结果不可预知。
Linux 的先辈 Unix 还有一个环境变量:LD_LIBRARY_PATH 来处理非标准路经的共享库。ld.so 加载共享库的时候,也会查找这个变量所设置的路经。
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:./lib export LD_LIBRARY_PATH
但是,有不少声音主张要避免使用 LD_LIBRARY_PATH 变量,尤其是作为全局变量
开发时,设置LIBRARY_PATH,以便gcc能够找到编译时需要的动态链接库。 发布时,设置LD_LIBRARY_PATH,以便程序加载运行时能够自动找到需要的动态链接库。
ld命令是二进制工具集GNU Binutils3的一员,是GNU链接器,用于将目标文件与库链接为可执行程序或库文件。
ld命令支持众多链接选项,但是大部分选项很少被使用,下面是GNU ld命令接受的选项。
xxxxxxxxxx
521-b <input-format>:指定目标代码输入文件的格式
2-Bstatic:只使用静态库
3-Bdynamic:只使用动态库
4-Bsymbolic:把引用捆绑到共享库中的全局符号
5-c <MRI-commandfile>,--mri-script=<MRI-commandfile>:为与MRI链接器兼容,ld接受由MRI命令语言编写的脚本文件
6--cref:创建跨引用表
7-d,-dc,-dp:即使指定了可重定位的输出文件(使用-r),也会为公共符号分配空间。脚本命令“FORCE_COMMON_ALLOCATION”具有相同的效果
8-defsym:在输出文件中创建指定的全局符号
9-demangle:在错误消息中还原符号名称
10-e <entry>:使用指定的符号作为程序的初始执行点
11-E,--export-dynamic:对于ELF格式文件,创建动态链接的可执行文件时,把所有符号添加到动态符号表
12-f <name>,--auxiliary=<name>:对于ELF格式共享对象,设置 DT_AUXILIARY 名称
13-F <name>,--filter=<name>:对于ELF格式共享对象,设置 DT_FILTER 名称。这告诉动态链接器,正在创建的共享对象的符号表应该用作共享对象名称的符号表的筛选器。
14-g:被忽略。用于提供和其他工具的兼容性
15-h:对于ELF格式共享对象,设置 DT_SONAME 名称
16-I<file>,--dynamic-linker=<file>:指定动态链接器。这仅在生成动态链接的ELF可执行文件时才有意义。默认的动态链接器通常是正确的,除非您知道正在做什么,否则不要使用该选项。
17-l <namespec>,--library=<namespec>:把指定的库文件添加到要链接的文件清单
18-L <searchdir>,--library-path=searchdir:把指定的路径添加添加到搜索库的目录清单
19-M,--print-map:显示链接映射,用于诊断目的
20-Map=<mapfile>: 将链接映射输出到指定的文件
21-m <emulation>: 模拟指定的链接器
22-N,--omagic: 指定读取/写入文本和数据段
23-n,--nmagic: 关闭节的页面对齐,并禁用对共享库的链接。如果输出格式支持Unix样式的幻数,则将输出标记为"NMAGIC"
24-noinhibit-exec:生成输出文件,即使出现非致命链接错误。通常,如果链接器在链接过程中遇到错误,它将不会生成输出文件。
25-no-keep-memory:ld通常在内存中缓存输入文件的符号表来优化内存使用速度。此选项告诉ld不要缓存符号表。当链接大型可执行文件时,如果ld耗尽内存空间,则可能需要使用该选项
26-O <level>:对于非零的优化等级,ld将优化输出。此操作会比较耗时,应该在生成最终的结果时使用。
27-o <output>,--output=<output>:指定输出文件的名称
28-oformat=<output-format>:指定输出文件的二进制格式
29-R <filename>,--just-symbols=<filename>:从指定的文件读取符号名称和地址
30-r,--relocatable:生成可重定位的输出(称为部分连接)
31-rpath=<dir>:把指定的目录添加到运行时库搜索路径
32-rpath-link=<dir>:指定搜索运行时共享库的目录
33-S,--strip-debug:忽略来自输出文件的调试器符号信息
34-s,--strip-all:忽略来自输出文件的所有符号信息
35-shared,-Bshareable:创建共享库
36-split-by-file[=size]:为每个目标文件在输出文件中创建额外的段大小达到size。size默认为1
37-split-by-reloc[=count]:按照指定的长度在输出文件中创建额外的段
38--section-start=<sectionname>=<org>:在输出文件中指定的地址定位指定的段
39-T <scriptfile>,--script=<scriptfile>:使用scriptfile作为链接器脚本。此脚本将替换ld的默认链接器脚本(而不是添加到其中),因此脚本必须指定输出文件所需的所有内容。如果当前目录中不存在脚本文件,“ld”会在-L选项指定的目录中查找
40-Ttext=<org>:使用指定的地址作为文本段的起始点
41-Tdata=<org>:使用指定的地址作为数据段的起始点
42-Tbss=<org>:使用指定的地址作为bss段的起始点
43-t,--trace:在处理输入文件时显示它们的名称
44-u <symbol>,--undefined=<symbol>:强制指定符号在输出文件中作为未定义符号
45-v,-V,--version:显示ld版本号
46-warn-common:当一个通用符号和另一个通用符号结合时发出警告
47-warn-constructors:如果没有使用任何全局构造器,则发出警告
48-warn-once:对于每个未定义的符号只发出一次警告
49-warn-section-align:如果为了对齐而改动了输出段地址,则发出警告
50--whole-archive:对于指定的存档文件,在存档中包含所有文件
51-X,--discard-locals:删除所有本地临时符号
52-x,--discard-al:删除所有本地符号
示例
xxxxxxxxxx
11ld /usr/lib64/crt1.o /usr/lib64/crti.o /usr/lib64/crtn.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib64 -L/usr/lib -lstdc++ -lm -lgcc_s -lc -lgcc main.o test.o -o test.out
ldconfig是一个动态链接库管理命令,其目的为了让动态链接库为系统所共享,做的是刷新动态链接库。
默认搜寻/lilb和/usr/lib,以及配置文件/etc/ld.so.conf内所列的目录下的库文件。
搜索出可共享的动态链接库,库文件的格式为:lib*.so.,进而创建出动态装入程序(ld.so)所需的连接和缓存文件。
缓存文件默认为/etc/ld.so.cache,该文件保存已排好序的动态链接库名字列表。
ldconfig通常在系统启动时运行,而当用户安装了一个新的动态链接库时,就需要手工运行这个命令。
xxxxxxxxxx
141ldconfig命令参数说明:
2
3-v或--verbose:用此选项时,ldconfig将显示正在扫描的目录及搜索到的动态链接库,还有它所创建的连接的名字.
4-n :用此选项时,ldconfig仅扫描命令行指定的目录,不扫描默认目录(/lib,/usr/lib),也不扫描配置文件/etc/ld.so.conf所列的目录.
5-N :此选项指示ldconfig不重建缓存文件(/etc/ld.so.cache).若未用-X选项,ldconfig照常更新文件的连接.
6-X : 此选项指示ldconfig不更新文件的连接.若未用-N选项,则缓存文件正常更新.
7-f CONF : 此选项指定动态链接库的配置文件为CONF,系统默认为/etc/ld.so.conf.
8-C CACHE :此选项指定生成的缓存文件为CACHE,系统默认的是/etc/ld.so.cache,此文件存放已排好序的可共享的动态链接库的列表.
9-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文件.用此选项,可以大大增加动态链接库管理的灵活性.
10-l :通常情况下,ldconfig搜索动态链接库时将自动建立动态链接库的连接.选择此项时,将进入专家模式,需要手工设置连接.一般用户不用此项.
11-p或--print-cache :此选项指示ldconfig打印出当前缓存文件所保存的所有共享库的名字.
12-c FORMAT 或--format=FORMAT :此选项用于指定缓存文件所使用的格式,共有三种:ld(老格式),new(新格式)和compat(兼容格式,此为默认格式).
13-V : 此选项打印出ldconfig的版本信息,而后退出.
14- 或 --help 或--usage : 这三个选项作用相同,都是让ldconfig打印出其帮助信息,而后退出.、
Windows程序在start时,同Linux一样,要将动态库load进来,Linux会查找LD_LIBRARY_PATH, Windows会查找环境变量PATH,以下是各平台的查找路径:
xxxxxxxxxx
71Linux: LD_LIBRARY_PATH
2Unix:
3Solaris:LD_LIBRARY_PATH
4HP: SHLID_PATH
5AIX: LIBPATH
6MacOS : PATH
7Windows: PATH
这些只是各平台会查找的其中一个路径,如Solaris就还会查找RPATH。 这不是这里要说的重点,在Linux及Unix平台上,程序在start时,如果查找到一个名字匹配,但格式不匹配的动态库,将报错,并退出,如32bit程序在LD_LIBRARY_PATH里面先找到了一个64bit的动态库,将报一个类似XXX.so: wrong ELF class: ELFCLASS64的错误,然后程序退出。 Windows平台不一样,使用Sysinternals utilities中的Procmon[Process Monitor ]工具可以看到,即使在PATH路径里面找到一个错误位数的dll,程序也会尝试将它读进来,并且从Procmon里看不到错误信息,但可以推测它load不成功,因为从Procmon里面看到程序继续查找PATH里面的其它路径,尝试去找到正常的dll,如果后面的路径有一个位数匹配的dll,程序就能load进来,成功运行起来。