Linux静态链接已经死了?

Shc*_*ein 61 linux gcc glibc static-linking

事实上,Linux上的-static gcc标志现在不起作用.让我引用GNU libc FAQ:

2.22.即使是静态链接的程序也需要一些我不能接受的共享库.我能做什么?

如果没有共享库,{AJ} NSS(详细信息只需输入`info libc"Name Service Switch"')将无法正常工作.NSS允许通过仅更改一个配置文件(/etc/nsswitch.conf)而不重新链接任何程序来使用不同的服务(例如NIS,文件,db,hesiod).唯一的缺点是现在静态库需要访问共享库.这由GNU C库透明地处理.

解决方案是使用--enable-static-nss配置glibc.在这种情况下,您可以创建一个仅使用服务dns和文件的静态二进制文件(为此更改/etc/nsswitch.conf).您需要明确链接所有这些服务.例如:

 gcc -static test-netdb.c -o test-netdb \
   -Wl,--start-group -lc -lnss_files -lnss_dns -lresolv -Wl,--end-group
Run Code Online (Sandbox Code Playgroud)

这种方法的问题在于您必须将使用NSS例程的每个静态程序与所有这些库链接起来.
{UD}事实上,不能再说使用此选项编译的libc正在使用NSS.没有开关了.因此,强烈 建议不要使用--enable-static-nss,因为这会使系统上程序的行为不一致.

关于这个事实,现在有什么合理的方法可以在Linux上创建一个功能齐全的静态构建,或者静态链接在Linux上完全没用?我的意思是静态构建:

  • 行为与动态构建完全相同(静态nss具有不一致的行为是邪恶的!);
  • 适用于glibc环境和Linux版本的合理变体;

小智 42

我认为这非常烦人,我认为将一个功能称为"无用"是很傲慢的,因为它在处理某些用例时遇到了问题.glibc方法的最大问题在于它硬编码到系统库(gconv以及nss)的路径,因此当人们尝试在不同于它的Linux发行版上运行静态二进制文件时,它会中断.

无论如何,您可以通过将GCONV_PATH设置为指向适当的位置来解决gconv问题,这允许我在Ubuntu上构建二进制文件并在Red Hat上运行它们.


Dum*_*001 27

关于这个事实,现在有什么合理的方法可以在Linux上创建一个功能齐全的静态构建,或者静态链接在Linux上完全没用?

我不知道在哪里可以找到历史性的引用,但是,静态链接在GNU系统上已经死了.(我相信它在从libc4/libc5过渡到libc6/glibc 2.x期间死亡)

根据以下情况,该功能被视为无用:

  • 安全漏洞.静态链接的应用程序甚至不支持libc的升级.如果app在包含lib漏洞的系统上链接,那么它将在静态链接的可执行文件中保持不变.

  • 代码臃肿.如果在同一系统上运行许多静态链接的应用程序,则不会重用标准库,因为每个应用程序都包含其自己的所有内容副本.(尝试du -sh /usr/lib了解问题的严重程度.)

尝试从10 - 15年前挖掘LKML和glibc邮件列表档案.我很确定很久以前我见过LKML相关的东西.

  • 不幸的是,他们没有提到另一方:静态链接二进制文件比启动动态链接对应文件花费少90%的时间来启动并且脏页面开销低得多.这些天,`glibc`的`eglibc`分支至少在一半时间内进行了静态链接,但是如果你想实际使用静态链接而没有巨大的二进制文件和像nss这样的bug /问题,你可能需要使用不同的libc实现. (38认同)
  • 我认为我的答案已经过时了:我已经静态链接了一个中等大小的应用程序,在Ubuntu 14.04上没有任何问题.但是静态链接错误的原因保持不变.当然,除非人们严重需要上面列出的奖金,否则它们将超过缺点. (3认同)

moo*_*oom 20

静态链接似乎并没有在Linux世界中获得太多爱.这是我的看法.

没有看到静态链接的吸引力的人通常在内核和低级操作系统的领域中工作.许多*nix库开发人员花了一辈子时间处理不可避免的问题,试图将一百个不断变化的库连接在一起,这是他们每天都在做的任务.如果你想知道他们喜欢的后空翻,请看一下autotools.

但是不应该让其他人花大部分时间在这上面.静态链接将为您从图书馆流失中缓冲带来很长的路要走.开发人员可以根据软件的计划升级其软件的依赖关系,而不是在出现新的库版本时被迫执行此操作.这对于面向用户的应用程序非常重要,这些应用程序具有复杂的用户界面,需要控制它们不可避免地依赖的许多低级库的流量.这就是为什么我将永远是静态链接的粉丝.如果你可以静态链接交叉编译的可移植C和C++代码,那么你几乎可以让世界成为你的牡蛎,因为你可以更快地向世界上不断增长的设备提供复杂的软件.

从其他角度来看,有许多不同意的地方,并且开源软件允许所有这些都很好.


Dea*_*ing 13

仅仅因为您必须动态链接到NSS服务并不意味着您无法静态链接到任何其他库.所有常见问题解答都说,即使是"静态"链接的程序也有一些动态链接的库.这并不是说静态链接是"不可能的"或它"不起作用".

  • 这意味着它不是完​​全静态的构建.事实上,在大多数情况下,它需要安装相同的glibc版本才能正常工作.为什么我需要这样的静态构建? (4认同)
  • @Dead:静态构建可执行文件没有动态链接器,因此无法加载共享库.我能找到的最佳参考:http://en.wikipedia.org/wiki/Static_build.正如我在下面写的那样,Linux并没有故意支持它. (2认同)

nh2*_*nh2 13

静态链接又重新兴起!

  • 许多(大多数?)Go编程语言可执行文件都是静态链接的。
    • 增加的可移植性和向后兼容性是它们流行的原因之一。
  • 其他编程语言也进行了类似的工作,以使真正的静态链接变得非常容易,例如Haskell(我正在努力)。
  • 可配置的Linux发行版 /软件包集(例如NixOS / nixpkgs)使静态链接其软件包的很大一部分成为可能(例如,其pkgsStatic软件包集可以提供各种静态链接的可执行文件)。
  • 静态链接可以在链接时更好地消除未使用的代码,从而使可执行文件更小。
  • 像musl这样的libcs使静态链接变得容易和正确。
  • 一些大型软件行业的领导人对此表示赞同。例如,谷歌正在针对静态链接编写新的libc“支持静态非PIE和静态PIE链接”“我们目前不打算在动态加载和链接支持方面进行投资”)。

  • 距离最初提出这个问题已有近 10 年了,这是一个好消息。我个人看到了这个优势,因为我在一个受监管的行业工作,我拥有的嵌入式目标对于“libc”更新不太灵活。但我始终可以随时为现场设备的(完全)静态链接程序提供新的二进制文件。 (2认同)

Far*_*hat 10

添加其他答案:

由于其他答案中提到的原因,它不推荐用于大多数Linux发行版,但实际上有一些发行版专门用于运行静态链接的二进制文件:

来自stali描述:

static linux基于手工选择的每个任务的最佳工具集合,每个工具都是静态链接的(包括一些X客户端,如st,surf,dwm,dmenu),

它还通过尽可能避免glibc和其他膨胀的GNU库来实现二进制大小减少(早期实验表明,静态链接的二进制文件通常比它们动态链接的glibc对应文件小!!!).请注意,这与Ulrich Drepper对静态链接的估计非常相反.

由于静态链接二进制文件开始更快的附带好处,该分发还针对性能增益.

静态链接也有助于减少依赖性.

您可以在有关静态与动态链接的问题中阅读更多相关信息.