【问题标题】:How to get a list of paths in /etc/ld.so.conf on Linux如何在 Linux 上获取 /etc/ld.so.conf 中的路径列表
【发布时间】:2011-07-13 03:55:06
【问题描述】:

获取由/etc/ld.so.conf 配置的路径列表以及其中包含的文件的最便携和最可靠的方法是什么?手动解析文件似乎不是一个好主意——格式可能会在未来的修订版中发生变化。


为了更好地理解这个问题,我将在下面为您提供具体细节。请注意,尽管有这些细节,但这是一个通用编程问题,适用于其他情况。

有一个程序,叫做LuaRocks。它是 Lua 编程语言的包管理器(有点像 Ruby gems 或 Python Eggs)。 LuaRocks 包被称为“rocks”。

作为一个方便的特性,LuaRocks 允许 Rock 作者为 Rock 指定外部依赖项列表,以 C 头文件和/或动态库文件的列表形式表示。 (Linux 上.so。)如果指定的文件不存在,则无法安装rock。

目前,在 Linux 上,LuaRocks 默认通过在两个 hardcoded 路径 /usr/lib/usr/local/lib 中搜索文件来检查 .so 文件是否存在。

我认为这是不正确的行为,它是 Ubuntu 和其他 Debian 发行版中最近的 changesbroken

更新:路径本身不是硬编码的,但用户可在配置文件中配置。尽管如此,IMO 并不是最好的解决方案。

相反(据我所知),LuaRocks 应该在/etc/ld.so.conf 指定的路径中查找文件以及其中包含的文件。

(现在请重新阅读上面的问题 ;-))

【问题讨论】:

    标签: linux lua shared-libraries debian ldd


    【解决方案1】:

    您不需要解析 /etc/ld.so.conf 或任何配置文件 - 如果您运行“ldconfig”,它将扫描配置的目录并生成缓存文件。

    随后,当您尝试 dlopen 时,它会通过遍历缓存的库目录自动查找文件。编译和提供 -lSomeLib 也是一样,如果你在 ld.so.conf(.d) 中配置了 -L/my/other/path,则不需要指定 -L/my/other/path

    autoconf 通过尝试编译链接到共享库的测试程序来实现这一点,但这只是 dlopen() 调用的功能包装器。

    因此,虽然其他方法不一定是“错误的”,但从根本上来说,尝试链接到库或执行 dlopen() 是“最正确”的方法。

    考虑到这一点,如果您尝试链接到目录中的库,而该目录中没有缓存在 /etc/ld.so.cache 中,当您尝试运行该程序时,它将失败,因为它无法dlopen() 图书馆!

    因此,任何“好的”共享库都将在 /etc/ld.so.cache 中并且可以链接/dlopen(),这意味着 gcc 可以使用它来链接,并且用户生成的库或可执行文件将执行时可以打开它。

    您可以通过明确设置环境变量 LD_LIBRARY_PATH 或 LD_PRELOAD_PATH 来规避此问题 - 但其中的每一个都有自己的警告,如果可能,应避免“标准”使用。

    一篇关于编写共享库的好文章涵盖了其中一些问题,对于任何致力于以编程方式使用其他共享库的人来说都是一本好书。 Ulrich Drepper's How to write shared libraries.

    【讨论】:

    • 问题与dlopen无关:LR必须在安装rock(和库)之前判断系统是否符合rock的合约。
    • 其实是因为dlopen()是操作系统查找动态库的方式。这些问题是相互交织的。也就是说,如果您运行 ldconfig,则无需“搜索”库 - 会自动找到它们。但。无论如何,感谢您的反对!
    • 您错过了重点 - 您将目录添加到 /etc/ld.so.conf.d/ 中的文件,然后运行 ​​ldconfig,ldconfig 生成 /etc/ld.so.cache,然后任何正在尝试查找共享库 'gcc foo.c -lMyLib',或 'ld -shared foo.c -lMyLib',或 'dlopen('MyLib')' 引用缓存 @ /etc/ld.so.cache,您不需要指定目录。这就是为什么当您安装新的共享库时 autoconf 会发出一条消息说“您应该重新运行 ldconfig 以更新您的缓存”。此时,您不必提供任何提示来制作/编译工具。
    • 再一次,你错过了重点。什么都不应该在特定目录中查找 .so 文件,这就是动态库存在的原因 - 否则 everything 将进入一个目录。如果您无法 dlopen 库,则它未在 /etc/ld.so.conf.d/* 中配置,并且在系统上表面上不可用。简而言之,什么都不应该“查看”/etc/ld.so.conf/*,任何事情都是以错误的方式做的。这不是观点,这是事实。 tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html
    • autoconf 通过尝试编译链接到共享库的测试程序来实现这一点,但这只是 dlopen() 调用的功能包装器。因此,虽然其他方法不一定是“错误的”,但从根本上来说,尝试链接到库或执行 dlopen() 是“最正确”的方法。考虑一下这一点,如果您尝试链接到一个未缓存在 /etc/ld.so.cache 中的库,当您尝试运行该程序时,它将失败,因为它无法 dlopen() 该库!因此,任何“好”的库都将位于 /etc/ld.so.cache 中并且可以链接/dlopen()。
    【解决方案2】:

    根据FHS,以下是动态库的有效位置:

    /lib*/
    /opt/*/lib*/
    /usr/lib*/
    /usr/local/lib*/
    

    (很可能还有~/lib*/。)

    我的/etc/ld.so.conf.d/* 中的所有条目都符合这一点。一些条目引用了 FHS 目录下的子目录,这可能意味着您可以在没有路径信息的情况下使用其中的库。

    现在我对 LuaRocks 的了解还不够。如果您仅限于 Lua 路径样式的 glob(仅限 ?),则无法匹配这些并且必须解析配置。否则,您可以尝试在这些目录中的任何位置找到它们。

    这会在不符合 FHS 的系统上中断(唯一选项:解析配置),如果配置中不包含目录,安装程序可能会看到链接器找不到的库。

    这两个对我来说似乎可以接受,因此我会简单地忽略配置并查看这些目录。

    (另一种可能是尝试链接库,这应该会自动使用正确的路径。但是,这是特定于平台的,可能很危险。)

    【讨论】:

    • Lua-path-style-globs 在这里无关紧要(我们正在讨论 LR 中的代码更改,所以无论如何这都不是问题)。
    • 在目录中直接查找看起来不够健壮——管理员用户可能会以不同的方式重新配置系统。
    • 出于性能和完整性的原因,链接库(或在其上调用 ldd)是不可接受的。
    • @Alexander,为什么不呢?对于安装程序来说,它应该相当快,除非你正在寻找几百个 solib。只需fork(),从分叉的进程中调用dlopen(),然后退出并显示退出代码指示您是否成功。
    • @Alexander:替代格式的lib目录在那边写成lib<qual>,你可以从ToC中找到它们。 <qual> 可以是任何东西,因此 *
    猜你喜欢
    • 1970-01-01
    • 2010-09-08
    • 1970-01-01
    • 1970-01-01
    • 2010-10-11
    • 2011-01-14
    • 2019-10-15
    • 2015-04-05
    相关资源
    最近更新 更多