我正在研究静态链接和动态链接,我的理解是,与动态链接相比,静态链接消耗更多的内存和磁盘空间。很明显,静态链接占用更多的磁盘空间,因为静态库被编译到每个可执行文件中。但是如何验证静态链接是否消耗更多的内存空间呢?为此,我设计了一个小实验,如下所述。
第一步:创建一个名为mylib. c的C文件
//mylib.c
#include <unistd.h>
// This function is designed to create a massive .text section.
void many_code() {
asm volatile (
"movabs $0x1122334455667788, %%rax \n\t"
"movabs $0x1122334455667788, %%rax \n\t"
"movabs $0x1122334455667788, %%rax \n\t" <----- This line is repeated one million times.
...
::: "rax"
);
sleep(-1);
}
第二步:执行gcc -c mylib. c-o mylib.o,将源文件编译成目标文件。
第三步:使用ar -r libmy.a mylib.o命令创建静态库
第四步:创建第二个C文件use_st_lib.c
// use_st_lib.c
extern void many_code();
int main() {
many_code();
return 0;
}
第五步:使用静态链接创建可执行文件use_st_lib_0.out,命令为“gcc use_st_lib.c -static libmy.a -o use_st_lib_0”。
第六步:使用静态链接创建第二个可执行文件,命令为“gcc use_st_lib. c-static libmy. a-o use_st_lib_1”。
➜ static git:(master) ✗ ls -hl
total 91M
-rw-r--r-- 1 root root 9.6M May 29 09:37 libmy.a
-rw-r--r-- 1 root root 51M May 27 23:33 mylib.c
-rw-r--r-- 1 root root 9.6M May 29 09:37 mylib.o
-rwxr-xr-x 1 root root 11M May 29 10:11 use_st_lib_0
-rwxr-xr-x 1 root root 11M May 29 10:12 use_st_lib_1
-rw-r--r-- 1 root root 76 May 27 22:10 use_st_lib.c
**第七步:在另一个终端会话中,使用top命令,设置刷新时间为1.0s。使用COMMAND=use_st_lib.**应用筛选条件
top - 10:21:59 up 15 days, 17:40, 4 users, load average: 0.00, 0.01, 0.05
Tasks: 79 total, 1 running, 78 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1.0 us, 1.0 sy, 0.0 ni, 98.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.8 free, 133.2 used, 829.5 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.8 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
第八步:使用./use_st_lib_0 &命令在后台运行进程use_st_lib_0。
➜ static git:(master) ✗ ./use_st_lib_0 &
[1] 31239
top - 10:31:06 up 15 days, 17:49, 4 users, load average: 0.07, 0.06, 0.06
Tasks: 80 total, 1 running, 79 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.6 free, 133.1 used, 829.8 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.9 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31239 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_0
第九步:使用“./use_st_lib_1 &"命令在后台运行进程use_st_lib_1。
➜ static git:(master) ✗ ./use_st_lib_1 &
[2] 31309
top - 10:32:02 up 15 days, 17:50, 4 users, load average: 0.03, 0.05, 0.05
Tasks: 81 total, 1 running, 80 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 1.0 sy, 0.0 ni, 99.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 1756.5 total, 793.3 free, 133.4 used, 829.9 buff/cache
MiB Swap: 0.0 total, 0.0 free, 0.0 used. 1469.6 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31309 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_1
31239 root 25 5 10.6m 9.5m 9.5m S 0.0 0.5 0:00.00 use_st_lib_0
以下是我的问题:
1,为什么我的程序在top命令的输出中显示SHR(共享内存)使用情况?(我希望这一列是0。)
2、启动use_st_lib_0后,RES(常驻内存)显示使用量为9.5m,但top命令顶部显示的内存使用量没有增加。(我预计它会从133.2使用改为123.7使用。)
3、类似地,在启动use_st_lib_1之后,top命令的输出显示很少或没有变化。(我预计它会从123. 7使用到114. 2使用。)
4、在上述步骤中,我在哪里犯了错误,或者我的理解可能出现了什么样的偏差?
以上是我所做的尝试和我所期望的结果。
1条答案
按热度按时间k2arahey1#
我的理解是静态链接比动态链接消耗更多的内存和磁盘空间。
这种理解是非常不完整的。
如果你有一个
./a.out
二进制文件,当完全静态链接时,这个二进制文件通常会消耗更少的内存和磁盘空间。这是因为:
PLT
和GOT
),也不需要用于动态重定位。这可能会消耗大量的空间。OTOH,如果你有多个二进制文件,它们都使用 * 相同 * 共享库,并且你同时运行所有这些二进制文件,那么它们使用的总内存和磁盘空间通常会比动态链接小,如果每个二进制文件都是完全静态链接的。
这是因为您不需要将库的副本作为每个可执行文件的一部分,也不需要将该库的代码多次加载到内存中。
另一个复杂之处是Linux使用了 * 按需分页 *,这意味着你的可执行文件不会消耗太多的RAM *,除非 * 它实际上运行了其中的所有代码,访问了数据,等等。
P.S.
使用
top
通常不是解决进程内存问题的好方法。它的输出可能非常具有误导性。请仔细阅读man top
。在Linux上,您可以通过查找
/proc/$pid/pagemap
(如果您的内核配置了CONFIG_PROC_PAGE_MONITOR
)来实际说明物理内存的每一页。