【问题标题】:In ELF library filenames, how important are the major and minor versions with regards to compatibility?在 ELF 库文件名中,主要和次要版本在兼容性方面有多重要?
【发布时间】:2014-05-29 13:42:20
【问题描述】:

我有一组安装在 Linux 机器上的二进制文件。它们需要libgfortran 库,但在执行时会显示以下消息:

error while loading shared libraries: libgfortran.so.2: cannot open shared object file: No such file or directory

机器已经安装了libgfortran,但是库文件的名称是libgfortran.so.1.0.0(和libgfortran.so.1链接到它)。

令我惊讶的是,只需将libgfortran.so.2libgfortran.so.1 建立一个符号链接,如下所示:

ln -s /usr/lib64/libgfortran.so.1 /usr/lib64/libgfortran.so.2

这解决了我的问题,并且二进制文件能够运行,显然没有错误。

我的问题是——他们为什么还要跑呢?

是否没有内置机制来检测 API 版本何时不同,还是仅基于文件名?

如果有 API 检测 - 那么应该没有符号错误吗?

确实,如果库之间具有不同的主要版本实际上是兼容的,那么它们的目的是什么?

(回答者注意:我的问题不是关于libgfortran,这只是一个说明性的例子。)

【问题讨论】:

    标签: linux versioning elf shared-libraries


    【解决方案1】:

    为什么它会运行?

    它运行是因为在 .so 中找到了所有依赖符号,所以它加载了

    是否有检测 API 版本差异的内置机制?

    有可用的符号版本控制支持,但您必须对其进行编程。这完全取决于开发者是否使用它。

    如果有API检测...?

    同样,有可用的符号版本控制,但并不完全相同。

    如果仍然兼容,拥有不同主要版本的目的是什么

    这取决于开发者。

    但请注意,可能只有您使用的 API 的元素在两个版本之间是兼容的。代码很可能会在后台默默地破坏您的数据,而您直到后来才意识到这一点。

    【讨论】:

    • 感谢您的回答。我假设某种形式的符号或库版本控制是所有共享库中固有的 - 没有意识到它实际上只是基于符号的聚合匹配!
    【解决方案2】:

    对于与先前版本兼容的 ABI 版本,次要版本通常会增加。 IE。当后者更新时,应用程序可以并且将使用新的次要版本共享库。

    对于与以前的主要版本不兼容 ABI 的版本,主要版本通常会增加。

    通常,一个共享库具有三个文件系统名称,例如:

    lrwxrwxrwx 1 max max       13 May 13 11:13 libfix.so -> libfix.so.0.0
    lrwxrwxrwx 1 max max       13 May 13 11:13 libfix.so.0 -> libfix.so.0.0
    -rwxrwxr-x 1 max max  1665544 May 13 11:13 libfix.so.0.0
    

    未版本化的libfix.so 只是完全版本化的符号链接。当您使用 ld 链接器将您的应用程序与 -lfix 链接时使用它。

    libfix.so.0.0 是实际的共享库。但是,此库与 -hlibfix.so.0 链接器选项链接:

       -h name
       -soname=name
           When creating an ELF shared object, set the internal DT_SONAME
           field to the specified name.  When an executable is linked with a
           shared object which has a DT_SONAME field, then when the executable
           is run the dynamic linker will attempt to load the shared object
           specified by the DT_SONAME field rather than the using the file
           name given to the linker.
    

    所以,当应用程序启动时,运行时链接器ld.so 实际上会查找libfix.so.0,它是指向具有相同主编号的最新版本共享库的符号链接。当libfix.so.0.0 更新为libfix.so.0.1 时,这些符号链接将更新为指向该新版本。现有的和新的应用程序会在您下次启动或链接它们时开始使用新版本的共享库。

    【讨论】:

    • 感谢您提供的信息。我想这意味着链接正确的库版本级别(例如在 fix.so、fix.so.0 或 fix.so.0.0 之间进行选择)是程序开发人员的责任,而不是库开发人员的责任?
    • @Ajjajj 开发人员通常只使用-lfix,这意味着他们大部分时间都想要最新版本。要链接到旧版本,人们通常添加类似libfix-compat.so symlink 的东西来指向旧的主要版本并使用-lfix-compat 链接它。
    猜你喜欢
    • 1970-01-01
    • 2012-10-11
    • 2017-04-22
    • 1970-01-01
    • 2021-12-28
    • 2013-09-22
    • 1970-01-01
    • 1970-01-01
    • 2014-06-08
    相关资源
    最近更新 更多