链接就是把不同的库文件合并成一个可执行文件,主要分为静态链接和动态链接.
静态链接主要完成这些工作:
- 符号表的建立
- 为各个链接单元里的变量和函数分配虚拟地址
- 合并相似段.比如libc和main.c的代码段合并到.text
如果编译时制定了静态链接-static
,相关的库文件会被直接链接好,形成一个很大的可执行程序.
采用动态链接,编译器不会把库文件合并,而是把相关工作推迟委托给链接器和装载器.
动态链接与静态链接最大的不同是,动态链接允许不同程序使用同一份库文件映.一般,操作系统把库文件的代码段加载好,用以进程共享,代码段一般不能被修改,是只读的;对于库文件的其他段,比如.data
和.bss
,每个进程都有一份独立的映像.
这种方法,直接导致了可执行文件的大小减小,并且多个程序执行时,占用的内存也较小.
静态链接的优点在于:
- 易于实现
- 防止运行时,由于某些库文件被改动(版本升级等),而造成接口不一致而运行失败.
我认为第二点是唯一的优点...
静态链接缺点在于:
- 占用空间太大.一方面,可执行文件在磁盘上就很大;另一方面,进程多了之后,内存出现大量重复的代码段,浪费空间.
- 不易于维护.只要有一个库文件产生了修改,整个可执行文件都要重新链接.不利于程序更新,我觉得
小米枪战
就可能是静态链接.
正式由于这些缺点才出现了动态链接,它的优点在于:
- 省空间,省内存
- 易于维护.只要API定义没变,就可以直接替换库文件.
- 允许程序运行期间,主动加载库文件,从而实现运行时更新.
缺点也有:
- 管理库文件比较麻烦.由于版本太多,链接时必须处理好.
- 程序启动的速度稍慢.
test.cpp文件编译后,两种方式下的可执行文件大小:
-rwxrwxr-x 1 moon moon 10kB 3月 4 15:53 shared_main.out*
-rwxrwxr-x 1 moon moon 2182kB 3月 4 15:53 static_main.out*