我试图理解 C 中共享库的以下行为
机器一
$ cat one.c
#include<stdio.h>
int main() {
printf ("%d", 45);
}
$ gcc one.c -o one -O3
$ ldd one
linux-gate.so.1 => (0x00331000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00bc2000)
/lib/ld-linux.so.2 (0x006dc000)
$ cat two.c
int main() {
int i = 0;
}
$ gcc two.c -o two -O3
$ ldd two
linux-gate.so.1 => (0x006f7000)
libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00eb0000)
$
机器二
$ cat three.c
#include<stdio.h>
int main() {
printf ("%d", 45);
}
$ gcc three.c -o three -O3
$ ldd three
/usr/lib/libcwait.so (0xb7ffd000)
libc.so.6 => /lib/tls/i686/nosegneg/libc.so.6 (0x002de000)
/lib/ld-linux.so.2 (0x002bf000)
$
目前我不完全理解的一些事情:
-
括号中给出的地址是什么(例如,(0x002de000)
) mean?
即使对于同一台机器上的同一个库,这些地址也是不同的,这表明这些是加载这些库的内存位置的地址。但是,如果这是真的,为什么这些库会加载到内存中(我还没有执行程序,它们不应该只在运行时加载吗?)。
-
为什么two
需要任何库吗?我用过-O3
,汇编器输出为
$ gcc two.c -S -O3
$ cat two.s
.file "two.c"
.text
.p2align 4,,15
.globl main
.type main, @function
main:
pushl %ebp
movl %esp, %ebp
popl %ebp
ret
.size main, .-main
.ident "GCC: (Ubuntu 4.4.3-4ubuntu5) 4.4.3"
.section .note.GNU-stack,"",@progbits
$
图书馆到底需要什么?
-
在二号机上,为什么/usr/lib/libcwait.so
被用来代替linux-gate.so.1
?
我认为这是因为机器二上的内核非常旧(2.6.9)并且库linux-gate.so.1
不可用。是这个原因吗?
括号中给出的地址(例如,(0x002de000))是什么意思?
它是加载库的(虚拟)内存地址。
最近的系统可以提供库加载位置的随机化,所以
该地址可能因调用而异。
它们不应该只在运行时加载吗?
是的,他们是。 ldd 经历的过程与
但在运行时完成,以便能够弄清楚各种事情。
为什么两个人都需要任何库?
libc.so.6 是标准 C 库(以及其他内容,例如内核接口),并且始终在默认情况下链接。 gcc 有选项来控制这一点,例如这-nostdlib
flag
ld-linux.so 是一个动态加载器,负责加载/重定位其他共享库并运行您的应用程序。 ld-linux.so 的联机帮助页为您提供了详细信息。
linux-gate.so.1是一个虚拟库,它只存在于内核的内存中。它用于执行对内核的系统调用,并根据您的 CPU 找出最有效的方法。这可能是比您的其他 2.6.9 内核机器更晚添加到 Linux 中的。
我不知道 /usr/lib/libcwait.so 是什么,但您可能可以通过执行 rpm -qif /usr/lib/libcwait.so 来获取有关它的一些信息
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)