您的位置:首页 > 其它

动态库,静态库,动态链接,静态链接

2015-07-14 01:56 246 查看
静态库和动态库

目前以lib后缀的库有两种,一种为静态链接库(Static Link Library),另一种为动态连接库(Dynamic Link Library DLL)的导入库(Import Libary)。

在静态库情况下,函数和数据被编译进一个二进制文件(通常扩展名为*.lib),编译器在处理程序代码时将从静态库中恢复这些函数和数据并把它们和应用程序中的其他模块组合在一起生成可执行文件。这个过程称为静态链接,此时因为应用程序所需的全部内容都是从库中复制了出来,所以静态库本身并不需要与可执行文件一起发行。

在动态库的情况下,有两个文件,一个是引入库(lib)文件,一个是dll文件。

引入库文件包含被dll文件导出的函数的名称和位置,dll包含实际的函数和数据,应用程序使用lib文件链接到所需要使用的dll文件,动态库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是dll中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。

动态库可以减少程序的大小,具有很高的灵活性。与静态库不同,动态库里面的函数不是执行程序本身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。

1. DLL在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地址空间分配的内存,成为调用进程的一部分。

2. DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;

3. 一个DLL在内存中只有一个实例,虽然可以被映射到不同进程的地址空间中;

4. DLL与具体的编程语言及编译器无关,可以通过DLL来实现混合语言编程。

5. DLL中所创建的任何对象(包括变量)都归调用它的线程或进程所有。

静态链接和动态链接

根据调用方式的不同,对动态库的调用可分为静态链接和动态链接。

(1)静态链接,也称为隐式链接,由编译系统完成对DLL的加载,和程序结束时DLL的卸载。一般是把导入库(.LIB)文件加入到应用程序的工程中。LIB文件包含了相应的DLL文件的名字,DLL导出函数的符号名和顺序表,不含有实际的代码。在导入库中找到外部函数后,会通知链接器此函数的代码在DLL中。要解析对DLL的外部引用,链接器只需向可执行文件中添加信息,通知系统在进程启动时应在何处查找DLL代码。

系统启动包含动态链接引用的程序时,它使用程序的可执行文件中的信息定位所需的DLL。如果系统无法定位DLL,它将终止进程并显示一个对话框来报告错误。否则,系统将DLL模块映射到进程的地址空间中。与程序代码的其余部分一样,DLL代码在进程启动时映射到进程的地址空间中,且仅当需要时才加载到内存中。

(2)动态链接,也称为显式链接,是由编程者用API函数加载和卸载DLL,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。

区别:

1. 如果在程序启动时未找到DLL,操作系统将终止使用隐式链接的进程。同样在此情况下,使用显式链接的进程则不会被终止,并可以尝试从错误中恢复。

2. 在应用程序启动时加载所有DLL,隐式链接到许多DLL启动起来会比较慢。

在Windows和Linux操作系统中,都可采用这种方式进行软件设计,但他们的调用方式以及程序编制方式不尽相同。



Windows动态库技术

windows中,每一个DLL必须有一个入口点,DllMain是一个缺省的入口函数。DllMain负责初始化(Initialization)和结束(Termination)工作。

在Windows系统中,与动态库调用有关的函数包括:

①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。

②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL内部地址。

③FreeLibrary(或MFC的AfxFreeLibrary),释放动态链接库。



DLL函数的导出:

①采用模块定义文件(.DEF)

②使用MFC提供的修饰符号_declspec(dllexport)

③以命令行方式,采用/EXPORT命令行输出有关函数。



Linux的动态库--共享对象技术

Linux采用共享对象技术(Shared Object),虽然它和Windows里的动态库相对应,但它并不称为动态库。相应的共享对象文件以.so作为后缀。同样,在Linux下,也有静态函数库,相应的后缀以.a结束。

在Linux中创建动态库,只需要在编译函数库源程序时加上-shared选项即可,这样所生成的执行程序就是动态链接库。

在Linux系统中,与动态库调用有关的函数包括:

(1)_打开动态链接库:dlopen,函数原型void *dlopen (const char *filename, int flag);

dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。

(2)取函数执行地址:dlsym,函数原型为: void *dlsym(void *handle, char *symbol);

dlsym根据动态链接库操作句柄(handle)与符号(symbol),返回符号对应的函数的执行代码地址。

(3)关闭动态链接库:dlclose,函数原型为: int dlclose (void *handle);

dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。

(4)动态库错误函数:dlerror,函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。

两种系统动态库比较分析

(1)动态库程序编写,在Windows系统下的执行文件格式是PE格式,动态库需要一个DllMain函数作为初始化的人口,通常在导出函数的声明时需要有_declspec(dllexport)关键字。

Linux下的gcc编译的执行文件默认是ELF格式,不需要初始化入口,亦不需要到函数做特别声明,编写比较方便。

(2)动态库调用方面,Windows和Linux对动态库都可以采用显式调用或隐式调用,但具体的调用方式也不尽相同。

(3)对操作系统的依赖,这两种动态库运行依赖于各自的操作系统,不能跨平台使用。因此,对于实现相同功能的动态库,必须为两种不同的操作系统提供不同的动态库版本。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: