让我先把一些事实摆在桌面上进行事实核查,以免造成混淆:
带有动态部分的 ELF 二进制文件在编译时会带有一些未解析的符号。解析将在二进制文件执行期间的某个时间由链接器执行。
动态链接有利也有弊。但是,如果您的二进制文件所需的目标库不存在于系统中(在所需版本中),则二进制文件将不会运行。
静态链接缓解了这个问题,但在下层引入了一个新问题。通过静态链接二进制文件,库的可执行代码嵌入到您的二进制文件中,因此二进制库接口不再有问题。但是,现在库-OS 界面可能会出现问题。那是对的吗?这里可能会出现什么问题?
现在让我们在 Go 的上下文中讨论这个问题。我注意到,如果我使用 构建一个二进制文件CGO_ENABLED=1 go build ...
,我会得到一个带有动态部分的二进制文件:
david@x1 /tmp (git)-[master] % readelf -d rtloggerd.cgo1
Dynamic section at offset 0x7a6140 contains 19 entries:
Tag Type Name/Value
0x0000000000000004 (HASH) 0x914e40
0x0000000000000006 (SYMTAB) 0x915340
0x000000000000000b (SYMENT) 24 (bytes)
0x0000000000000005 (STRTAB) 0x915100
0x000000000000000a (STRSZ) 570 (bytes)
0x0000000000000007 (RELA) 0x914a38
0x0000000000000008 (RELASZ) 24 (bytes)
0x0000000000000009 (RELAENT) 24 (bytes)
0x0000000000000003 (PLTGOT) 0xba6000
0x0000000000000015 (DEBUG) 0x0
0x0000000000000001 (NEEDED) Shared library: [libpthread.so.0]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000006ffffffe (VERNEED) 0x914de0
0x000000006fffffff (VERNEEDNUM) 2
0x000000006ffffff0 (VERSYM) 0x914d80
0x0000000000000014 (PLTREL) RELA
0x0000000000000002 (PLTRELSZ) 816 (bytes)
0x0000000000000017 (JMPREL) 0x914a50
0x0000000000000000 (NULL) 0x0
另一方面,如果 I 时CGO_ENABLED=0 go build ...没有动态部分:
130 david@x1 /tmp (git)-[master] % readelf -d rtloggerd.cgo0
There is no dynamic section in this file.
这是否意味着库是静态链接的?我想是的,但大小差异在我的机器上可以忽略不计(大约 72 kB),这让我感到惊讶。
关于跨 Linux 系统的可移植性,哪个更好,为什么?
Go的标准库是如何开展业务的呢?它实际上是在调用libc
(在我的例子中)提供的 C 函数吗?glibc
我假设有一个本地系统调用接口。另一方面,我想在原生 Go 中重新实现整个 stdlib 会很困难。
最后,我听说“不能保证不同的发行版,甚至同一发行版的不同版本都兼容 ABI”。这是真的?我假设 ABI 主要是二进制可执行格式(Linux 上的 ELF 有一段时间),所以我假设这里没有问题。这意味着什么?
谢谢!
杨__羊羊
相关分类