摘要

动态连结 VS 静态联结

By Wing

动态连结 VS 静态联结

  在 Linux 中,执行档我们能够编程成静态联结连同动态连结,以下我们举一个简短的程式作为例子:



#include  

int main() 

{ 

printf(" test"); 

} 

  若我们执行 :



[root@hlchou /root]# gcc test.c -o test 

  所产生出来的执行档 test,预设为使用动态函式库,所以我们能够用以下的指令 :



[root@hlchou /root]# ldd test 

libc.so.6 => /lib/libc.so.6 (0x40016000) 

/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000) 

  来得知现在该执行档共用了哪些动态函式库,以我们所举的 test 执行档来说,共用了两个动态函式库,分别为 libc.so.6 和 ld-linux.so.2。我们还能够透过下面的 file 指令,来得知该执行档的相关属性,如下



[root@hlchou /root]# file test 

test: ELF 32-bit LSB executable, Intel 80386, version 1, dynamically 

linked (use s shared libs), not stripped 

  not stripped 表示这个执行档还没有透过 strip 指令来把执行时用不到的符号、连同相关除错的资讯删除,举个例子来说,现在这个test 执行档大小约为 11694 bytes



[root@hlchou /root]# ls -l test 

-rwxr-xr-x 1 root root 11694 Oct 24 02:31 test 

  经过strip後,则变为 3004 bytes



[root@hlchou /root]# strip test 

[root@hlchou /root]# ls -l test 

-rwxr-xr-x 1 root root 3004 Oct 24 02:48 test 

  但是读者必须注意到一点,经过 strip 过的执行档,就无法透过其他的除错软件从里面取得函式在编程时所附的相关资讯,这些资讯对我们在除错软件时,能够提供不少的帮助,各位在应用上请自行注意。

  相对於编程出来使用动态函式库的执行档 test,我们也能够做出静态联结的执行档 test



[root@hlchou /root]# gcc -static test.c -o test 

  透过指令 ldd,我们能够确定执行档 test 并没有使用到动态函式库



[root@hlchou /root]# ldd test 

not a dynamic executable 

  再透过指令 file,能够注意到 test 现在为 statically linked,且亦尚未经过 strip



[root@hlchou /root]# file test 

test: ELF 32-bit LSB executable, Intel 80386, version 1, statically 

linked, not stripped 

  相信大夥都会好奇,使用静态联结,且又没有经过 strip 删去不必要的符号的执行档的大小会是多少,透过 ls -l来看,我们发现大小变成 932358 bytes 比起静态联结的执行档大了相当多



[root@hlchou /root]# ls -l test 

-rwxr-xr-x 1 root root 932258 Oct 24 02:51 test 

  若再经过 strip,则档案大小变为 215364 bytes



[root@hlchou /root]# strip test 

[root@hlchou /root]# ls -l test 

-rwxr-xr-x 1 root root 215364 Oct 24 02:55 test 

  和使用动态函式库的执行档 test 比较起来,大了约 70倍 (215364/3004)。因此,整体来说,在使用的环境中使用动态函式库并且经过 strip 处理的话,能够让整体的空间较为精简。许多执行档都会用到同一组的函式库,像 libc 中的函式是每个执行档都会使用到的,若是使用动态函式库,则能够尽量减少同样的函式库内容重复存在系统中,进而达到节省空间的目的。

  笔者一年前曾写过一个能够用来删去动态函式库中不必要函式的工具,针对这个只用到了 printf 的程式来产生新的 libc.so 的话,我们能够得到一个精简过的 libc.so 大小约为 219068 bytes



[root@hlchoua lib]# ls -l libc.so* 

-rwxr-xr-x 1 root root 219068 Nov 2 04:47 libc.so 

lrwxrwxrwx 1 root root 7 Nov 1 03:40 libc.so.6 -> libc.so 

  和静态联结的执行档大小 215364 bytes 比较起来,若是在这个环境中使用了动态函式库的话成本约为 3004 219068 =222072 bytes,但是这是只有一个执行档的情况下,使用动态函式库的环境会小输给使用静态联结的环境,在一个基本的 Linux 环境中,假如大量的使用动态函式库的话,像是有 2 个以上的执行档的话,那用动态函式库的成本就大大的降低了,像假如两个执行档都只用到了 printf,那静态联结的成本为 215364 *2 =430728 bytes,而使用动态函式库的成本为3004 *2 219068=225076 bytes,两者相差约一倍。

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!