静态链接与动态链接浅尝

静态链接:
静态链接在程序装载前进行,链接器通过符号解析和重定位将目标文件(windows平台下为.o文件)进行链接,链接后形成可执行文件(如exe文件),静态链接使得不同的程序开发者和部门能够相对独立的开发和测试自己的程序模块,从某种意义上来讲大大促进了程序开发的效率,原先限制程序的模块也随之扩大,但是慢慢的静态链接的诸多缺点也逐渐暴露出来,比如浪费内存和磁盘空间,模块更新困难等问题。
静态链接的原理很简单,但是实践起来比较难,在早期操作系统和硬件不发达的时候,绝大部分系统采用这种方案,随着计算机软件的发展,这种方法的缺点很快就暴露出来了,那就是静态链接对计算机的内存和磁盘空间浪费非常严重。特别是多进程操作系统环境下,静态链接极大的浪费了内存空间,想象一下每个程序内部除了保留着printf()函数、scanf()函数等这样的公用库函数,还有相当数量可观的其他库函数以及他们所需要的辅助数据结构,在现在的windows系统中,一个普通程序会使用到的C语言静态库至少在1MB以上,那么如果我们的机器上运行着2000个这样的程序,就要浪费近2GB的磁盘空间及内存空间,想想都不可行。
静态链接与动态链接浅尝
如图Program1和Program2分别包含Program1.o和Program2.o两个模块,并且他们还共用Lib.o模块,在静态链接情况下,Lib.o同时在链接输出的可执行文件Program1和Program2中有两个副本,因此浪费了磁盘空间,装载时分别运行浪费了内存空间。
动态链接:
要解决空间浪费和更新困难这两个问题最简单的办法就是把程序模块相互分离开来,形成独立的文件,而不再将他们静态的链接在一起,简单的说就是不对那些组成程序的目标文件进行链接,等到程序运行时再进行链接,也就是说把链接过程推迟到了运行时进行,这就是动态链接的基本思想。
还是以Program1和Program2为例,假设我们保留Program1.o、Program2.o和Lib.o三个目标文件,当我们运行Program1的时候,首先加载Program1.o,当系统发现Program1.o用到了Lib.o,即Program1.o依赖于Lib.o,那么 系统接着加载Lib.o,如果Lib.o和Program1.o还依赖于其他文件,系统会按照这种方法将他们全部加载至内存,所有需要的目标文件加载完毕后,如果依赖关系满足,即所有依赖的目标文件都存在于磁盘,系统开始通过符号解析和重定位等进行链接,完成链接后,动态链接器把控制权交给程序Program1.o入口处,程序开始运行。这时我们运行Program2,那么系统只需要加载Program2.o,而不需要重新加载Lib.o,因为系统中已经存在了Lib.o的副本,系统只需将Program2.o和lib.o链接起来即可。
静态链接与动态链接浅尝
显然上面这种做法,磁盘和内存只存在一份lib.o,而不是两份,节省了内存和磁盘空间,同时动态链接使得开发过程中各个模块更加独立耦合度更小,便于不同的开发者和开发组织之间独立进行 开发和测试。
动态链接包括载入时链接和运行时链接
载入时链接:程序启动过程中将功能模块读入内存时将所依赖动态库的相关模块的内容载入内存,缺点启动较慢,但是功能运行时较快。
运行时链接:是在执行程序调用到模块内容时再将动态库中的相应模块载入到内存(如插件)。缺点功能运行较慢,但是程序启动较快。