系统与基础设施eli.thegreenplace.net
静态链接程序如何在 Linux 上运行
How statically linked programs run on Linux
2012 — 2014,它一次次回到首页
黑点是上首页(≥ 50 分)的那次投稿,空心点是没冲上去的投稿,点越大分数越高。
导读
这篇文章详细解释了Linux内核如何加载和运行静态链接的程序,涵盖从ELF可执行文件格式、系统调用execve到程序入口点的全过程。通过与动态链接对比,展示了静态链接程序自包含、无需运行时链接器介入的特性。
为什么经久不衰:以清晰易懂的方式深入底层细节,是理解程序加载与链接机制的经典入门材料,多年来持续被参考。
HN 评论精选
对比Windows上共享库与静态链接的历史,指出Delphi因静态链接而避免了DLL地狱。
有意思的对比是Windows上的做法。大多数C++程序能在所有Windows电脑上运行(且文件那么小),是因为Windows自带了所需的公共库(C++运行时)。当Borland推出Delphi时,他们希望微软能包含一些自己的公共库以减少可执行文件大小——但微软拒绝了,意味着Delphi的可执行文件必须把所有东西静态链接进去,导致文件大了一个数量级。抛开90年代在意文件大小的污名不谈,他们在这一点上可以说占了上风,因为Delphi默认避免了‘DLL地狱’(直到微软在Windows 2000中彻底解决),而且可以在任何东西上运行,无需额外依赖。
mickeyp查看英文原文
The interesting contrast here is how things are done on Windows. The reason most C++ programs ran on all Windows computers (and with such a tiny file size) is Windows shipped with the common libraries (C++ runtime) required to run the programs. When Borland came out with Delphi they wanted Microsoft to include some of their own common libraries to reduce the footprint of the executable -- but Microsoft said no, meaning Delphi's executables had to have everything linked into it statically, resulting in files that were an order of magnitude bigger. Aside from the stigma from larger file sizes in an era (the 90s) when this mattered, they arguably came out ahead in this department as Delphi by default avoided "DLL hell" (until MS solved it more or less definitively with Windows 2000) and would run anywhere, on anything, with no additional dependencies.
强调静态链接程序启动和fork/exec更快,反驳fork慢的迷思,并以使用shell脚本的web框架为例。
许多人不知道的一件事:静态链接的程序比动态链接的程序运行快得多!具体来说,它们启动快得多,动态链接程序的fork()/exec()要慢得多,而对于静态链接程序来说,这比大多数人想象的要快得多。有一个fork很慢的迷思,导致人们放弃了像CGI这样简单、优雅和Unix风格的解决方案。我用rc shell写了一个完整的Web‘框架’(http://werc.cat-v.org),现实是,如果你静态链接你的程序,你可以使用每个请求执行几十次fork的shell脚本,仍然比php加fcgi之类提供更好的性能。(另一个很棒的事情是,shell脚本和管道自然且神奇地利用了多核系统,Unix再次美丽地展示了像fork和管道这样简单而美丽的概念在发明几十年后有着意想不到的好处。)
luriel查看英文原文
One thing many people are not aware of: statically linked programs run much faster than dynamically linked ones! Or to be specific, they start up much faster, fork()/exec() are much slower for dynamically linked programs, while for statically linked programs it is much faster than most people think. There is a myth that forking is slow, and that caused people to abandon very simple, elegant and unixy solutions like CGI. I wrote a whole web "framework" in rc shell ( http://werc.cat-v.org) and the reality is that if you statically link your programs you can use shell scripts that do dozens of forks per request and still provide better performance than something like php with fcgi. (Another great thing is that shell scripts and pipes naturally and automagically take advantage of multi-core systems, Unix once again beautifully shows how simple and beautiful concepts like fork and pipes have unforeseen benefits many decades after they were invented.)
指出Linux上静态链接的困难,社区对二进制分发的敌意,以及GCC和链接器的改进。
TL;DR:祝你好运!至少直到最近,实际上几乎不可能做到这一点——Autopackage曾经有一份清单,列出了阻碍为Linux制作体面的可移植二进制包的事情。我相信他们最终交付了一个修改过的链接器来让事情运转起来。不幸的是,在Linux上简化二进制分发遭到很多敌意,因为普遍存在着‘你应该使用共享库,为什么你会想分发二进制文件,既然你可以直接分发源代码?’的态度。话虽如此,GCC几年前终于添加了一个真正的静态链接选项(即不是`-static`)。而且我相信链接器终于支持符号版本化了。
Timmmmbob查看英文原文
TL;DR: Good luck! At least until recently it was virtually impossible to actually do this - Autopackage used to have a list of things that prevented making decently portable binary packages for Linux. I believe they resorted to shipping a modified linker to get things to work. Unfortunately there is a lot of hostility to making binary distribution easier on Linux because of the "you should be using shared libraries and why would you ever want to distribute binaries when you can just distribute the source code?" attitude that prevails. Having said that, GCC did finally add a real option to link statically (i.e. not `-static`) a few years ago. And I believe the linker finally supports symbol versioning.
质疑静态编译大型C/C++环境的实用性,并对比Go的交叉编译静态二进制文件的便利。
对于现代基于C/C++的软件环境,静态编译和链接大部分内容真的实际可行吗?上次我用一个不简单的C程序和GCC尝试这样做时,感觉就像一场最终不成功的徒劳搜寻。顺便提一下,交叉编译静态二进制文件是Go的一个极其高效的功能。
fiatmoney查看英文原文
Is it actually practical to statically compile & link large parts of a modern C / C++ based software environment? The last time I tried to do that with a nontrivial C program and GCC it felt like an ultimately unsuccessful snipe hunt. Incidentally, cross-compiling static binaries is a hugely productive feature of Go.
历次讨论
同类还值得读
TTY 揭秘(2008)
The TTY demystified (2008)
经典文章深入剖析了 Unix/Linux 中 TTY 子系统的工作原理,包括线路规程、终端驱动、信号与控制字符等机制。
系统与基础设施上首页 11 次 · 2009–2025linusakesson.net编辑精选为什么 GNU grep 这么快
Why GNU grep is Fast
FreeBSD 邮件列表上一篇广为流传的帖子,解释 GNU grep 为什么快:核心在于 Boyer-Moore 字符串搜索算法配合精心优化的内部循环和 I/O,让程序在搜索时“…
系统与基础设施上首页 9 次 · 2010–2022lists.freebsd.orgXplain:为普通人讲解 X11
Xplain – Explaining X11 for the rest of us
《Xplain》是作者(HN 用户 Jasper_)写的一系列 X11 长文,用他在浏览器中重建的 X11 绘图模型做交互演示,讲解 X11 的绘图模型与窗口系统设计。
系统与基础设施上首页 6 次 · 2013–2020magcius.github.io编辑精选旋风教程:为 Linux 创建极小 ELF 可执行文件(1999)
A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux (1999)
breadbox 写于 1999 年的经典教程,主题是如何为 Linux 手工构造并裁剪出体积极小的 ELF 可执行文件。
系统与基础设施上首页 6 次 · 2007–2025muppetlabs.comPostgreSQL 内部原理
The internals of PostgreSQL
《The Internals of PostgreSQL》是一本免费在线书籍,系统讲解 PostgreSQL 的内部实现,包括查询处理、并发控制、WAL、缓冲区管理等核心机制。
系统与基础设施上首页 5 次 · 2017–2025interdb.jp编辑精选