静态链接 libc,可能与否,推荐与否?

静态链接 libc,可能与否,推荐与否?

我在我的二进制文件中看到这一行:

0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

难道我不应该摆脱它吗?实际上更令人困惑的是,为什么它首先存在,我觉得 gcc 默认编译只在主机上运行的东西有点疯狂。仅仅依赖于一些随机的 libc 是不是非常危险,这些随机 libc 可能位于也可能不在我最终将这个二进制文件复制粘贴到的机器上?我不明白。在 Windows 上,我认为我会收到某种“缺少运行时”错误,该错误的版本控制为我编译它所用的确切运行时,因此,如果我使用特定编译器在 XP 上进行编译,则任何主机也必须安装该运行时。但在 Linux 上我从未听说过这样的情况,或者某处是否有 50 个不同的 libc.so 目录,并且当我的应用程序尝试启动时正确的目录被链接?因为我有一种感觉,Linux 上确实存在 .dll 地狱,但实际情况并非如此。

答案1

至少对于 GNU C 库,链接携带所使用的每个符号(函数等)的版本信息。您可以使用objdump -T;查看此内容例如,在 上/bin/ls,我得到

DYNAMIC SYMBOL TABLE:
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3   __ctype_toupper_loc
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 __uflow
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 getenv
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 sigprocmask
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.3.4 __snprintf_chk
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 raise
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 free
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 abort

ETC。

C 库开发人员竭尽全力确保 C 库保持向后兼容。上面的输出意味着ls需要__ctype_toupper_loc2.3 或更高版本的 C 库等。任何提供所有必需符号的 C 库都将能够运行给定的二进制文件;并且任何给定版本的 GNU C 库都提供旧版本 C 库(可追溯到 1997 年)所提供的所有符号的实现。

另一种处理方式是 soname,它被基于 Linux 的系统(实际上是基于 ELF 的系统和其他系统)上的大多数库所使用。每个库不仅定义其名称,还定义版本号,每当引入重大更改时(在某些情况下更频繁),版本号都会更改。可以并行安装具有不同soname的多个版本的库;例如

-rw-r--r--  1 root root  2500416 Dec 16 21:07 libcrypto.so.1.0.2
-rw-r--r--  1 root root  2711616 Nov 28 23:43 libcrypto.so.1.1

(这是由 C 库使用,如依赖项名称所示,libc.so.6但最后一次 GNU C 库 soname 碰撞发生在很多年前。)

为了解决标题中的问题,可以静态链接 C 库,但很少有必要或有用(并且可能会令人困惑,因为即使 C 库是静态链接的,C 库的某些部分也是动态链接的)。静态链接其他库可能很有用。其他语言使用不同的方法,例如 Go 程序是静态链接的。

相关内容