我了解如何在链接/编译时定义包含共享对象。但是,我仍然想知道可执行文件在执行时如何查找共享对象(*.so库)。例如,我的应用程序a.out调用了lib.so库中定义的函数。编译后,我将lib.so移至我的$HOME中的新目录。

如何告诉a.out去那里寻找它?

评论

一个快速的解决方案是使用g ++ -Wl,-R。这将迫使加载程序在当前文件夹中查找so库。或-Wl,-R $ HOME / path指定其他一些固定文件夹。

#1 楼

共享库HOWTO解释了所涉及的大多数机制,动态加载程序手册也有更详细的说明。每个unix变体都有自己的方式,但是大多数使用相同的可执行格式(ELF),并且具有类似的动态链接程序¹(源自Solaris)。下面,我将重点介绍Linux的常见行为。
(术语注释:系统中加载共享库的部分通常称为“动态链接器”,但有时更确切地说是“动态加载器”。“动态链接器”可以也表示在编译程序时为动态加载程序生成指令的工具,或编译时工具与运行时加载程序的组合。在此答案中,“链接器”是指运行时部分。)简而言之,当寻找动态库(.so文件)时,链接器将尝试:

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

rpath存储在可执行文件中(即DT_RPATHDT_RUNPATH动态属性)。它可以包含绝对路径或以$ORIGIN开头的路径以指示相对于可执行文件位置的路径(例如,如果可执行文件位于/opt/myapp/bin中,并且其rpath为$ORIGIN/../lib:$ORIGIN/../plugins,则动态链接程序将在/opt/myapp/lib/opt/myapp/plugins中查找)。通常,在编译可执行文件时使用r4312079q的-rpath选项来确定rpath,但之后可以使用ld对其进行更改。
在您描述的场景中,如果您是应用程序的开发人员或打包人员,并打算将其安装在chrpath…/bin结构中,请与…/lib链接。如果要在系统上安装预构建的二进制文件,请将库放在搜索路径上的目录中(如果您是系统管理员,则为-rpath='$ORIGIN/../lib',否则为添加到/usr/local/lib的目录),或尝试使用$LD_LIBRARY_PATH。 br />

评论


在某些系统上,/ lib64和/ usr / lib64用于64位二进制文​​件,而/ lib和/ usr / lib用于32位二进制文​​件。

–马克·拉卡塔(Mark Lakata)
2015年6月4日18:21

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

–爱概率
18年6月19日在6:50

@LovesProbability因为问题在于可执行文件在哪里寻找库,而这些库不涉及ldconfig。安装库时,ldconfig会参与其中。

–吉尔斯'所以-不再是邪恶的'
18年6月19日在22:26

请注意,*。so库的“系统搜索路径”与$ PATH不同。搜索路径由@enzotib在其答案中给出。要打印出将要搜索的路径,请运行ldconfig -v 2> / dev / null | grep -v ^ $'\ t'。

–安德鲁·贝特(Andrew Bate)
19年6月21日在18:22



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

–罗伯特·拉格(Robert Lugg)
19-10-9在20:02

#2 楼

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



评论


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

–瑟斯登·斯塔克
2014年12月6日在7:30

问题是关于运行时间,而不是链接时间

– Talespin_Kit
15年3月6日在10:25

#3 楼

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


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

#4 楼

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

其中1234是正在运行的可执行文件的pid。

Linux遵循LD_LIBRARY_PATH和其他变量,正如Gilles在回答中指出的。

评论


很高兴您在第二句话中确认吉尔斯的答案会有所帮助。但是,第一部分完全没有解释如何告诉a.out文件在哪里,只有在已经找到文件的情况下才告诉它们。总而言之,这仅是评论,而不是答案。

–安东
15年10月15日在15:24