参考:
1、http://blog.csdn.net/cmiaomiaozoo/article/details/4734200
2、http://baike.baidu.com/view/945739.htm
1、静态链接
静态链接是由链接器在链接时将库的内容加入到可执行程序中的做法。(链接器是一个独立程序,将一个或多个库或目标文件(由编译器或汇编器生成)链接到一块生成可执行程序。)
静态链接的最大缺点是生成的可执行程序太大,需要更多的系统资源,在装入内存时也会消耗更多的时间。
像Unix ld程序这样的静态链接器(static linker)以一组可重定位的目标文件作为输入,生成一个完全连接的可以加载和运行的可执行目标文件作为输出。输入的可重定位目标文件由各种不同的代码和数据节(section)组成。指令在一个节中,初始化的全局变量在一个节中,而未初始化的变量在另外一个节中。
为了构造可执行文件,链接器必须完成两个主要的任务:
1、符号解析(symbol resolution)。目标文件定义和引用符号。符号解析的目的是将每个符号引用刚好和一个符号定义联系起来。
2、重定位(relocation)。编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义和一个存储器位置联系起来,然后,修改所有对这些符号的引用,使得他们指向这个存储器位置,从而重定位这些节。
2、动态链接
2-1、基本思想
静态链接使得不同的程序开发者和部门能够相对独立地开发和测试自己的程序模块,从某种意义上来讲大大促进了程序的开发效率,原先限制程序的规模也随之扩大。但是慢慢地静态链接的诸多缺点也逐步暴露出来,比如浪费内存和磁盘空间、模块更新困难等问题,使得人们不得不寻找一种更好的方式来组织程序的模块。
要解决空间浪费和更新困难这两个问题最简单的办法就是把程序的模块相互划分开来,形成独立的文件,而不再将他们静态地链接在一起。简单地讲,就是不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。也就是说,把链接这个过程推迟到了运行时再进行,这就是动态链接(Dynamic Linking)的基本思想。
2-2、实现过程
动态链接,在可执行文件装载时或运行时,由操作系统的装载程序加载库。
2-2-1、装载时链接
大多数操作系统将解析外部引用(比如库)作为加载过程的一部分。在这些系统上,可执行文件包含一个叫做import directory的表,该表的每一项包含一个库的名字。根据表中记录的名字,装载程序在硬盘上搜索需要的库,然后将其加载到内存中预先不确定的位置,之后根据加载库后确定的库的地址更新可执行程序。可执行程序根据更新后的库信息调用库中的函数或引用库中的数据。这种类型的动态加载成为装载时加载 ,被包括Windows和Linux的大多数系统采用。装载程序在加载应用软件时要完成的最复杂的工作之一就是加载时链接。
Windows在搜索要装入的DLL时,采用顺序:
应用程序所在目录——当前目录——Windows SYSTEM目录——Windows目录——PATH环境变量指定的路径。
2-2-2、运行时链接
其他操作系统可能在运行时解析引用。在这些系统上,可执行程序调用操作系统API(如LoadLibrary和GetProcAddress),将库的名字,函数在库中的编号和函数参数一同传递。操作系统负责立即解析然后代表应用调用合适的函数。这种动态链接叫做运行时链接 。因为每个调用都会有系统开销,运行时链接要慢得多,对应用的性能有负面影响。现代操作系统已经很少使用运行时链接。
可以动态链接的库,在Windows上是dynamic link library (DLL),在UNIX或Linux上是Shared Library(SO)。库文件是预先编译链接好的二进制文件,存储在计算机的硬盘上。大多数情况下,同一时间多个应用可以使用一个库的同一份拷贝,操作系统不需要加载这个库的多个实例。
2-3、缺点
动态链接的最大缺点是可执行程序依赖分别存储的库文件才能正确执行。如果库文件被删除了,移动了,重命名了或者被替换为不兼容的版本了,那么可执行程序就可能工作不正常。这就是常说的DLL-hell。
3、windows api与dll:
windows api中的所有函数均包含在dll中,其中最为重要的3个windows api的dll文件是:
(1)Kernel32.dll 主要是管理内存、进程和线程的函数的集合;
(2)User32.dll 执行用户界面的任务的函数(比如:窗口的创建销毁放大缩小、消息的传递等等与用户相关的操作);
(3)GDI32.dll 包含用于画图和显示文本的各个函数。
4、引入库和动态库:
引入库和动态库是成对出现的,在编译dll的时候会同时产生一个引入库,扩展名为lib。lib中仅含有dll中的函数名和参数,真正的函数体在动态库中。两个的关系大概相当于.h和.cpp文件之间的关系。
5、引入库和静态库:
引入库和静态库的扩展名均为*.lib,但是引入库仅包含一些函数名和参数信息,没有函数体,是为调用动态库服务的,它和动态库的关系也相当于.h文件和.cpp文件之间的关系。