144 linux dynamic-linking
我知道 Linux 下的共享对象使用“so numbers”,即不同版本的共享对象被赋予不同的扩展名,例如:
example.so.1example.so.2我理解这个想法是有两个不同的文件,以便系统上可以存在两个版本的库(而不是 Windows 上的“DLL Hell”)。我想知道这在实践中是如何工作的?通常情况下,我看到example.so其实是一个符号链接到example.so.2这里.2是最新版本。那么依赖于旧版本的应用程序如何example.so正确识别它?对于必须使用的数字是否有任何规则?或者这只是惯例?是否与在系统之间传输软件二进制文件的 Windows 不同,如果系统具有较新版本的共享对象,它会在从源代码编译时自动链接到较旧版本?
我怀疑这与有关,ldconfig但我不确定如何。
Mic*_*zek 97
二进制文件本身知道它们依赖的共享库的哪个版本,并专门请求它。您可以使用ldd来显示依赖项;我的ls是:
$ ldd /bin/ls
linux-gate.so.1 => (0xb784e000)
librt.so.1 => /lib/librt.so.1 (0xb782c000)
libacl.so.1 => /lib/libacl.so.1 (0xb7824000)
libc.so.6 => /lib/libc.so.6 (0xb76dc000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb76c3000)
/lib/ld-linux.so.2 (0xb784f000)
libattr.so.1 => /lib/libattr.so.1 (0xb76bd000)
Run Code Online (Sandbox Code Playgroud)
如您所见,它指向 eg libpthread.so.0,而不仅仅是libpthread.so.
符号链接的原因是链接器。当你想libpthread.so直接链接时,你给出gccflag -lpthread,它会自动添加lib前缀和.so后缀。您不能告诉它添加.so.0后缀,因此符号链接指向最新版本的 lib 以方便
mig*_*aza 63
共享库中的数字是 Linux 中用来标识库 API 的约定。通常格式为:
libFOO.so.MAJOR.MINOR
Run Code Online (Sandbox Code Playgroud)
正如你注意到的,通常有一个从 libFOO.so 到 libFOO.so.MAJOR.MINOR 的符号链接。ldconfig 负责将此链接更新到最新版本。
MAJOR 通常在 API 更改(删除新入口点或更改参数或类型)时递增。MINOR 通常会在错误修复版本或在不破坏现有 API 的情况下引入新 API 时增加。
更广泛的讨论可以在这里找到:剖析共享库
小智 30
共享库应根据以下方案进行版本控制:
blah.so.X.Y.Z
Run Code Online (Sandbox Code Playgroud)
在哪里
通常你只看到第一个数字,hello.so.1因为第一个数字是唯一需要识别库的“版本”的东西,因为所有其他数字都是向后兼容的。
ldconfig维护一个表,其中包含系统上可用的共享库以及该库的路径存在的位置。您可以通过运行来验证这一点:
ldconfig -p
Run Code Online (Sandbox Code Playgroud)
当为 Red Hat 之类的东西构建包时,在二进制文件中调用的共享库将被查找并在 RPM 构建时作为包的依赖项添加。因此,当您去安装该软件包时,安装程序会hello.so.1通过检查ldconfig.
您可以通过执行以下操作来查看包的依赖项:
rpm -qpR hello.rpm
Run Code Online (Sandbox Code Playgroud)
该系统(与 Windows 不同)允许hello.so在一个系统上安装多个版本的 ,并同时由不同的应用程序使用。
pen*_*359 22
libNAME.so 是编译器/链接器首次查找由 -lNAME 指定的库时使用的文件名。共享库文件中有一个名为 SONAME 的字段。当库本身第一次被构建过程链接到一个共享对象(so)时,这个字段被设置。这个 SONAME 实际上是链接器存储在可执行文件中的内容,具体取决于与其链接的共享对象。通常 SONAME 采用 libNAME.so.MAJOR 的形式,并且在库与链接到它的现有可执行文件不兼容时进行更改,并且可以根据需要保留安装库的两个主要版本(尽管只有一个会被指向用于开发)如 libNAME.so) 此外,为了支持在库的次要版本之间轻松升级,libNAME.so.MAJOR 通常是指向 libNAME.so.MAJOR.MINOR 等文件的链接。可以安装新的次要版本,一旦完成,指向旧次要版本的链接就会指向新的次要版本,立即升级所有新执行以使用升级后的库。另外,请参阅我对Linux、GNU GCC、ld、版本脚本和 ELF 二进制格式——它是如何工作的?