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


101

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

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

我该如何告诉我a.out去那里找呢?

Answers:


101

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

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

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

rpath存储在可执行文件中(它是DT_RPATHor DT_RUNPATH动态属性)。它可以包含绝对路径或以开头的路径,$ORIGIN以指示相对于可执行文件位置的路径(例如,如果可执行文件在其中,/opt/myapp/bin而其rpath是,$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


3
在某些系统上,/lib64/usr/lib64用于64位二进制文​​件,并且/lib/usr/lib用于32位二进制文​​件。
Mark Lakata 2015年

为什么这个正确的答案不谈ldconfig
Loves Probability

1
@LovesProbability因为问题在于可执行文件在哪里寻找库,而这并不涉及ldconfigldconfig安装库时会涉及到。
吉尔斯

1
请注意,“系统搜索路径”为*.so库是一样的$PATH。搜索路径由@enzotib在其答案中给出。要打印出将要搜索的路径,请运行ldconfig -v 2>/dev/null | grep -v ^$'\t'
安德鲁·贝特

对我来说,要运行ldconfig,我需要/sbin/ldconfig安德鲁·贝特(Andrew Bate)的其他魔力来使其非root用户运行
Robert Lugg

16

在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.

1
“默认目录,通常是/ lib和/ usr / lib。” ->如何确定我的系统是否正常?
Thorsten Staerk

2
问题是关于运行时间而不是链接时间
Talespin_Kit 2015年

2

我很确定这里的答案是ldconfig

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

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


0

对于正在运行的应用程序,该文件/proc/1234/maps包含所有实际的动态链接库。

1234运行的可执行文件的pid 在哪里。

吉尔斯在回答中指出,Linux遵循LD_LIBRARY_PATH和其他变量。


4
很高兴您在第二句话中确认Gilles的回答会有所帮助。但是,第一部分完全没有解释如何告诉a.out文件在哪里,只有在已经找到文件的情况下才告诉它们。总而言之,这仅是评论,而不是答案。
安东2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.