本文简单介绍静态链接和动态链接,它们主要的区别就是如何链接程序库。
通常我们写程序,即使是简单的hello world
小程序,要链接C
程序库。复杂的程序,还要链接额外的程序库。如果是静态链接,就会把程序库里面被编译程序所需要的部分拿出来,集成到最终的执行程序中,在程序运行的时候,就不再依赖系统里面部署的程序库,或者说,即使系统里面没有我们需要的程序库也没关系,程序照样运行。而动态链接则不会把程序库的内容集成到执行程序中,因此,如果程序要想成功在某个系统下运行,那么它所需要的程序库必须部署在该系统里,否则无法运行。
静态链接和动态链接各有优劣。静态链接的缺点主要有两个:浪费系统空间和升级困难。由于每一个应用程序里面都有一份程序库的拷贝,那么系统里可能就会有成千上万个程序库的拷贝,它们的存在没有意义,而且如果程序库需要升级,则每个依赖它的应用程序都需要重新编译一遍,浪费大量时间。静态链接也有好处,它使得移植程序相对容易,在开始阶段采用静态链接,可以把精力集中在应用程序本身,没有问题之后,再去考虑和系统的集成。
动态链接的优缺点正好和静态链接相对,提高系统空间利用率、升级程序库无需重新编译相关应用程序,但是应用程序对系统的依赖程度提高,有可能增大开发和移植的难度。
使用gcc
,缺省情况下是动态链接,如果需要静态链接,可以使用-static
参数。使用ldd
或者readelf
可以查看一个程序是静态链接还是动态链接,例子如下:
$ gcc -o hello hello.c $ ldd hello linux-gate.so.1 => (0x005d6000) libc.so.6 => /lib/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x00c4e000) $ gcc -static -o hello_static hello.c $ ldd hello_static not a dynamic executable $ readelf -d hello Dynamic section at offset 0xf28 contains 20 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x0000000c (INIT) 0x8048290 0x0000000d (FINI) 0x804846c 0x6ffffef5 (GNU_HASH) 0x804818c 0x00000005 (STRTAB) 0x80481fc 0x00000006 (SYMTAB) 0x80481ac 0x0000000a (STRSZ) 74 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0x8049ff4 0x00000002 (PLTRELSZ) 24 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x8048278 0x00000011 (REL) 0x8048270 0x00000012 (RELSZ) 8 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffe (VERNEED) 0x8048250 0x6fffffff (VERNEEDNUM) 1 0x6ffffff0 (VERSYM) 0x8048246 0x00000000 (NULL) 0x0 $ readelf -d hello_static There is no dynamic section in this file.
很好的科普系列文章,继续期待。
多谢捧场啊,我也是边学习边写,以免荒芜了小站。