可执行文件在运行时在哪里查找共享对象?

rah*_*hmu 159 compiling path executable dynamic-linking

我了解如何在链接/编译时定义包含共享对象。但是,我仍然想知道可执行文件*.so在执行时如何查找共享对象(库)。

例如,我的应用程序a.out调用lib.so库中定义的函数。编译后,我移动lib.so到我的$HOME.

我怎么知道a.out去那里找呢?

Gil*_*il' 155

共享库HOWTO解释了大部分所涉及的机制,并且动态加载程序手册进入更多细节。每个 unix 变体都有自己的方式,但大多数使用相同的可执行格式 ( ELF ) 并具有类似的动态链接器¹(源自 Solaris)。下面我将重点总结 Linux 的常见行为;检查您的系统手册以了解完整的故事。

(术语说明:系统中加载共享库的部分通常称为“动态链接器”,但有时更准确地说是“动态加载器”。“动态链接器”也可以指在编译时为动态加载器生成指令的工具一个程序,或者编译时工具和运行时加载器的组合。在这个答案中,“链接器”指的是运行时部分。)

简而言之,当它寻找动态库(.so文件)时,链接器会尝试:

  • LD_LIBRARY_PATH环境变量中列出的目录(DYLD_LIBRARY_PATH在 OSX 上);
  • 在可执行文件的rpath 中列出的目录;
  • 系统搜索路径上的目录(至少在 Linux 上)由/etc/ld.so.confplus/lib/usr/lib.

rpath 存储在可执行文件中(它是DT_RPATHorDT_RUNPATH动态属性)。它可以包含绝对路径或以 开头的路径,$ORIGIN以指示相对于可执行文件位置的路径(例如,如果可执行文件位于/opt/myapp/binrpath 中,$ORIGIN/../lib:$ORIGIN/../plugins则动态链接器将查找/opt/myapp/lib/opt/myapp/plugins)。rpath 通常是在编译可执行文件时确定的,-rpath选项为ld,但您可以在之后使用chrpath.

在您描述的场景中,如果您是应用程序的开发人员或打包人员并打算将其安装在…/bin,…/lib结构中,则使用-rpath='$ORIGIN/../lib'. 如果您要在系统上安装预先构建的二进制文件,请将库放在搜索路径上的目录中(/usr/local/lib如果您是系统管理员,否则是您添加到的目录$LD_LIBRARY_PATH),或者尝试chrpath.

  • 在某些系统上,`/lib64` 和 `/usr/lib64` 用于 64 位二进制文​​件,`/lib` 和 `/usr/lib` 用于 32 位二进制文​​件。 (4认同)
  • @LovesProbability因为问题是关于可执行文件在哪里寻找库,这不涉及“ldconfig”。当您安装库时,会涉及“ldconfig”。 (3认同)
  • 请注意,“*.so”库的“系统搜索路径”与“$PATH”不同。搜索路径由@enzotib 在他们的答案中给出。要打印出将搜索的路径,请运行 `ldconfig -v 2>/dev/null | grep -v ^$'\t'`。 (3认同)

enz*_*tib 19

在 Linux 中,该行为在ld(1)手册页中明确说明

       The linker uses the following search paths to locate required
       shared libraries:

       1.  Any directories specified by -rpath-link options.

       2.  Any directories specified by -rpath options.  The difference
           between -rpath and -rpath-link is that directories specified by
           -rpath options are included in the executable and used at
           runtime, whereas the -rpath-link option is only effective at
           link time. Searching -rpath in this way is only supported by
           native linkers and cross linkers which have been configured
           with the --with-sysroot option.

       3.  On an ELF system, for native linkers, if the -rpath and
           -rpath-link options were not used, search the contents of the
           environment variable "LD_RUN_PATH".

       4.  On SunOS, if the -rpath option was not used, search any
           directories specified using -L options.

       5.  For a native linker, the search the contents of the environment
           variable "LD_LIBRARY_PATH".

       6.  For a native ELF linker, the directories in "DT_RUNPATH" or
           "DT_RPATH" of a shared library are searched for shared
           libraries needed by it. The "DT_RPATH" entries are ignored if
           "DT_RUNPATH" entries exist.

       7.  The default directories, normally /lib and /usr/lib.

       8.  For a native linker on an ELF system, if the file
           /etc/ld.so.conf exists, the list of directories found in that
           file.

       If the required shared library is not found, the linker will issue
       a warning and continue with the link.
Run Code Online (Sandbox Code Playgroud)

  • 问题是关于运行时而不是链接时间 (7认同)
  • “默认目录,通常是 /lib 和 /usr/lib。” -> 如何得知我的系统是否正常? (2认同)

Sea*_* C. 5

我很确定这里的答案是ldconfig

ldconfig 创建必要的链接并缓存到在命令行指定的目录、文件 /etc/ld.so.conf 和受信任的目录(/lib 和 /usr/lib)中找到的最新共享库。缓存由运行时链接器 ld.so 或 ld-linux.so 使用。ldconfig 在确定应更新其链接的版本时,会检查它遇到的库的标头和文件名。

http://linux.die.net/man/8/ldconfig