动态链接库及静态链接库(windows下的.dll.lib和linux下的.so.a)
- 格式:docx
- 大小:33.82 KB
- 文档页数:9
linux动态库和静态库调用方法
在Linux操作系统中,动态库和静态库的调用方法如下:
1. 动态库(Shared Library):动态库在程序运行时被载入内存,可以被多个程序同时使用,节省内存空间。
在Linux中,动态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中使用extern "C"来声明函数接口,然后通过dlopen(), dlsym()等函数来动态调用动态库中的函数。
2. 静态库(Static Library):静态库在程序编译时被包含进可执行程序中,每个程序都有一份自己的库副本。
静态库一般存放在/usr/lib或/lib目录下。
调用方法:在程序中直接使用静态库中的函数,不需要额外的调用方法。
只需要在编译时使用"-l"选项指定要链接的库名,例如"gcc -o test test.c -lmylib"。
需要注意的是,对于动态库和静态库的使用,一般建议优先使用动态库,因为这样可以节省内存空间,并且可以在不停止程序运行的情况下更新库文件。
第1页/ 共1页。
现在PC平台流行的可执行文件格式(Executable)主要是Windows下的PE(Portabl e Executable)和Linux的ELF(Executable Linkable Format),它们都是COFF(C ommon file format)格式的变种。
不光是可执行文件(Windows的.exe和Linux下的ELF可执行文件)按照可执行文件格式存储。
动态链接库(DLL,Dynamic Linking Library)(Windows的.dll和Linux 的.so)及静态链接库(Static Linking Library)(Windows的.lib和Linux的.a)文件都按照可执行文件格式存储。
它们在Windows下都按照PE-COFF格式存储,Linux 下按照ELF格式存储。
看完上面的资料你是已经知道ELF是什么作用了吧?其实就是Unix下的可执行文件和动态库(*.so)和目标文件(*.o)文件格式。
目标文件有三种类型:1. 可重定位文件(Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。
(Linux的*.o 文件Windows的*.obj文件)2. 可执行文件(Executable File)包含适合于执行的一个程序,此文件规定了exec() 如何创建一个程序的进程映像。
(比如/bin/bash文件;Windows的*.exe)3. 共享目标文件(Shared Object File)包含可在两种上下文中链接的代码和数据。
首先链接编辑器可以将它和其它可重定位文件和共享目标文件一起处理,生成另外一个目标文件。
其次,动态链接器(Dynamic Linker)可能将它与某个可执行文件以及其它共享目标一起组合,创建进程映像。
目标文件全部是程序的二进制表示,目的是直接在某种处理器上直接执行(Linux的.so,如/lib/ glibc-2.5.so;Windows的DLL)A:调用操作系统的api不同,除非是纯asm并且没有操作系统的int调用,没有全局变量和类的地址空间的分配,这些与操作系统调用有关(或者说是dll 文件之类)的调用,是可以跨平台执行。
vmprotect使用方式vmprotect是一种用于保护软件和应用程序的工具,它可以帮助开发者防止软件被破解、盗版和逆向工程等恶意行为。
本文将介绍如何使用vmprotect来保护软件和应用程序。
为了使用vmprotect,我们需要下载并安装它。
vmprotect提供了Windows和Linux版本,根据自己的操作系统选择相应的版本进行下载和安装。
安装完成后,我们可以开始使用vmprotect来保护我们的软件。
首先,打开vmprotect的界面,我们可以看到一个简单的操作界面。
在这里,我们可以选择要保护的文件,并设置不同的保护选项。
在选择文件时,我们可以点击“添加文件”按钮,然后选择需要保护的软件或应用程序文件。
vmprotect支持多种文件格式,包括可执行文件(.exe)、动态链接库(.dll)和静态链接库(.lib)等。
选择文件后,我们可以设置不同的保护选项来增强软件的安全性。
vmprotect提供了多种保护选项,包括代码虚拟化、加密、反调试和反反汇编等。
通过组合使用这些选项,我们可以有效地防止软件被破解和盗版。
其中,代码虚拟化是vmprotect的核心功能之一。
它可以将软件的机器码转换为虚拟指令,使得逆向工程师很难还原出原始的源代码。
虚拟指令的执行需要通过vmprotect提供的虚拟机来完成,这增加了破解的难度。
除了代码虚拟化,加密也是一种常用的保护选项。
vmprotect可以对软件的关键部分进行加密,使得黑客无法直接查看和修改这些代码。
加密后的代码只有在运行时才会被解密,这有效地防止了恶意行为。
反调试和反反汇编也是常用的保护选项。
vmprotect可以检测和阻止调试器的运行,防止黑客通过调试软件来破解和修改代码。
同时,vmprotect还可以使软件的反汇编结果变得混乱和不可读,增加逆向工程的难度。
在设置完保护选项后,我们可以点击“保护”按钮来开始保护软件。
vmprotect会根据我们的配置对软件进行相应的保护操作。
动态库技术1、介绍动态库是程序设计常用的技术,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理。
在Windows和Linux操作系统中都有动态库的概念。
Windows将其称为动态链接库(Dynamic Link Library,DLL),其文件扩展名为.dll,Linux称其为共享库技术(Shared Library),相应的共享库文件扩展名为.so。
故名思义,动态库在程序运行的时候被动态链接。
但是在具体使用动态库的时候却有两种不同的方式:隐式链接和显式链接。
隐式链接在编译/链接阶段完成,由编译系统根据动态库的头文件和库文件进行编译和链接,从而确定待调用的函数原形和地址。
显式链接则是利用API函数实现加载和卸载共享库,获取带调用函数地址,获取错误信息等功能。
2、隐式链接举例(1)动态库文件代码:dl_func.c#include extern char name[];int add(int a, int b){printf("calling add\n");printf("Hello, %s!\n", name);return a + b;}该文件中的add()函数计算两个整数之和,并且打印外部变量的值,该外部变量由调用共享库的事例程序定义。
(2)客户端事例代码:dl_demo1.c#include#includeint add(int a, int b);char name[100];int main(intargc, char *argv[]){int a = 10, b = 20;int c = 0;strcpy(name, "NHN XDBMS");c = add(a, b);printf("%d + %d = %d\n", a, b, c);return 0;}该事例程序调用共享库的中的add()函数计算两数之后并打印,同时在事例程序中,给变量name赋值,以便在add()函数中打印。
dll原理DLL原理动态链接库(Dynamic Link Library,简称DLL)是一种Windows 操作系统中常用的库文件,它可以被多个应用程序共享使用,从而避免了重复编写相同的代码。
本文将详细介绍DLL的原理。
一、静态链接与动态链接在介绍DLL原理之前,先来了解一下静态链接和动态链接。
1. 静态链接静态链接是指将程序所需要的库文件在编译时全部打包进可执行文件中。
这样做的好处是程序运行时不需要再加载外部库文件,因此速度较快。
但缺点也很明显,即可执行文件体积较大,在多个程序中使用相同的库时会造成重复浪费。
2. 动态链接动态链接是指在程序运行时才加载所需的库文件。
这样做的好处是节省了内存空间,并且多个程序可以共享同一个库文件。
但缺点也很明显,即运行速度较慢。
二、DLL概述1. DLL定义DLL是一个包含可由多个程序同时使用的代码和数据的库文件。
它可以被多个应用程序共享使用,从而避免了重复编写相同的代码。
2. DLL分类根据DLL所包含函数是否可以被其他应用程序调用,DLL可以分为两种类型:(1)导出函数的DLL导出函数的DLL是指将其中一些函数导出,以便其他应用程序可以调用这些函数。
这种DLL文件通常包含一组API(Application Programming Interface,应用程序编程接口)函数。
(2)内部使用的DLL内部使用的DLL是指不导出任何函数,只供当前进程中的其他模块使用。
这种DLL文件通常包含一些共享数据和实现某些功能的代码。
三、DLL加载过程1. 加载方式当一个应用程序需要调用一个DLL中的函数时,Windows操作系统会自动加载该DLL。
Windows操作系统有两种加载方式:(1)显式链接显式链接是指在编译时就将要使用的DLL文件名和需要调用的函数名写入源代码中,并在程序运行时由操作系统自动加载该DLL文件。
(2)隐式链接隐式链接是指在编译时不将要使用的DLL文件名和需要调用的函数名写入源代码中,而是在程序运行时由操作系统自动搜索并加载相应的DLL文件。
库的简介和分类⼀、库的分类: 静态库:库中代码被嵌⼊到可执⾏程序或动态库中,扩展名为“.lib” 动态库:库中代码不被嵌⼊到可执⾏程序或其它动态库中,只在运⾏时加载,扩展名为“.dll” 简介: 1)由于静态库是将代码嵌⼊到使⽤程序中,多个程序使⽤时,会有多份代码,所以代码体积会增⼤,但是程序运⾏效率较⾼。
动态库代码只需⼀份,其它程序通过函数地址以共享⽅式使⽤动态库中的代码,所以体积⼩。
2)静态库发⽣变化后,新的代码需要重新链接(嵌⼊)到使⽤程序中。
动态库发⽣变化后,只要函数的接⼝(函数名+参数表+返回类型)未发⽣变化,使⽤该动态库的程序⽆需重新链接。
3)静态链接库中不能再包含其他的动态链接库或者静态库,⽽在动态链接库中还可以再包含其他的动态或静态链接库 4)我们在Windows⽬录下的system32⽂件夹中会看到kernel32.dll(处理内存管理和进程调度)、user32.dll(控制⽤户界⾯)和gdi32.dll(负责图形操作),windows的⼤多数API都包含在这些DLL中。
5)VC中动态库分为三种,分别是:Non-MFC DLL(⾮MFC动态库)、MFC Regular DLL(MFC规则DLL)、MFC Extension DLL(MFC扩展DLL)⼆、库的调⽤ 1、对静态库的调⽤,须⽤“#pragma coment(lib,".lib⽂件的相对路径")”来通知链接器寻找库的路径,C++程序调⽤C语⾔静态库(.c⽣成的.lib)/C语⾔动态库(.c⽣成的.dll .lib)中的函数时,须在进⾏函数声明时在函数原型的前⾯加上:extern "C";对于动态库的调⽤,动态库中的函数/类须导出,⽽在调⽤动态库中的函数/类时须导⼊,须将⽣成的动态库⽂件(.dll)与调⽤程序的执⾏⽂件(.exe)放在同⼀⽬录下,程序才可运⾏。
2、C++程序在调⽤C语⾔库(C语⾔静态库/C语⾔动态库(静态调⽤时))、C++库(C++静态库/C++动态库(静态调⽤时))中的函数时,须进⾏函数声明。
编辑编译连接执行过程中对应的文件扩展名在编写、编译、连接和执行程序的过程中,不同的文件扩展名用于标识不同类型的文件。
下面是一些常见的文件扩展名及其相应的用途:
1. 源代码文件扩展名:
- .c:C语言源代码文件
- .cpp:C++语言源代码文件
- .java:Java语言源代码文件
- .py:Python语言源代码文件
- .html:HTML网页源代码文件
2. 目标文件扩展名:
- .o:目标文件,包含已编译但未链接的二进制代码
- .obj:Windows系统上的目标文件
- .class:Java字节码文件
3. 库文件扩展名:
- .a:静态库文件(在Unix和Linux系统中)
- .lib:静态库文件(在Windows系统中)
- .so:共享库文件(在Unix和Linux系统中)
- .dll:动态链接库文件(在Windows系统中)
4. 可执行文件扩展名:
- .exe:Windows可执行文件
- .out:Unix和Linux可执行文件
- .app:MacOS可执行文件
除了这些常见的文件扩展名之外,还有一些特定于某些开发环境或语言的扩展名。
例如,对于Web开发,还有.css(样式表文件)、.js (JavaScript文件)和.php(PHP脚本文件)。
对于数据库开发,还有.sql(SQL脚本文件)。
这些扩展名用于标识特定类型的文件,并告诉编译器、连接器和操作系统如何处理它们。
在编写程序时,应根据所使用的编程语言和工具链的要求为文件选择正确的扩展名。
这样可以确保编译、连接和执行过程能够正确进行,并且生成正确的可执行文件或库文件。
DLL与LIB文件的区别共有两种库:一种是LIB包含了函数所在的DLL文件和文件中函数位置的信息(入口),代码由运行时加载在进程空间中的DLL提供,称为动态链接库dynamic link library。
一种是LIB包含函数代码本身,在编译时直接将代码加入程序当中,称为静态链接库static link library。
共有两种链接方式:动态链接使用动态链接库,允许可执行模块(.dll文件或.exe文件)仅包含在运行时定位DLL函数的可执行代码所需的信息。
静态链接使用静态链接库,链接器从静态链接库LIB获取所有被引用函数,并将库同代码一起放到可执行文件中。
关于lib和dll的区别如下:(1)lib是编译时用到的,dll是运行时用到的。
如果要完成源代码的编译,只需要lib;如果要使动态链接的程序运行起来,只需要dll。
(2)如果有dll文件,那么lib一般是一些索引信息,记录了dll中函数的入口和位置,dll中是函数的具体内容;如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。
使用静态编译的lib 文件,在运行程序时不需要再挂动态库,缺点是导致应用程序比较大,而且失去了动态库的灵活性,发布新版本时要发布新的应用程序才行。
(3)动态链接的情况下,有两个文件:一个是LIB文件,一个是DLL文件。
LIB包含被DLL导出的函数名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到DLL 文件。
在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中相应函数代码的地址,从而节省了内存资源。
DLL 和LIB文件必须随应用程序一起发行,否则应用程序会产生错误。
如果不想用lib文件或者没有lib文件,可以用WIN32 API函数LoadLibrary、GetProcAddress装载。
使用lib需注意两个文件:(1).h头文件,包含lib中说明输出的类或符号原型或数据结构。
Linux和Windows平台动态库.so和.dll⽂件的⽣成Linux动态库的⽣成1、纯cpp⽂件打包动态库将所有cpp⽂件和所需要的头⽂件放在同⼀⽂件夹,然后执⾏下⾯命令gcc -shared - fpic *.c -o xxx.so;g++ -std=c++17 - fpic *.cpp -o xxx.so;[C++17标准,需要⾼版本gcc,本⼈采⽤gcc 8.2.0]其中*.c代表所有的c⽂件,xxx.so中的xxx代表so动态库的名字, -std=c++17代表采⽤C++17标准编译。
2、多个cpp⽂件和so库⼀起打包成⼀个sog++ -std=c++17 -fpic AFClassifier.cpp -shared -L. -lRandom -o test.so3、多个so打包为⼀个so如果有两个so,分别为 libRandom.so和libAF.so,并且在当前⽬录下⾯,则执⾏下⾯命令:g++ -std=c++17 -fpic -shared -L. -lAF -lRandom -o test.so如果libRandom.so和libAF.so不在当前⽬录,-L 后⾯要加上⽬录,⽐如在当前⽬录的下⼀层⽬录,则:g++ -std=c++17 -fpic -shared -L ./ -lAF -lRandom -o test.so===========================================================Windows动态库的打包(dll)1、打开⼯程,在解决⽅案中打开属性—》配置属性:做以下修改:“⽬标⽂件扩展名”:由默认的exe修改为dll“配置类型”:选择动态库dll同时注意配置和平台的版本。
最好把release和debug下⾯的配置属性都做上⾯的修改。
2、在接⼝⽂件(也就是最重要的头⽂件)添加两处代码:1)#ifdef LIBRARY_EXPORTS# define LIBRARY_API __declspec(dllexport)#else# define LIBRARY_API __declspec(dllimport)#endif2)在调⽤函数前⾯加上“LIBRARY_AP”当然如果在接⼝函数前⾯直接写上__declspec(dllimport)有时也可以,但是当遇到静态变量或者静态函数时,就不⾏了,我⾃⼰没有真实测试过,看的博⽂这样介绍的,博⽂连接如下:3、点击⽣成解决⽅案,即可⽣成.dll⽂件。
vs编译动态链接库和静态链接库的方法在Visual Studio(VS)中编译动态链接库(DLL)和静态链接库(LIB)的方法略有不同。
以下是具体的步骤:编译动态链接库(DLL)1. 打开Visual Studio。
2. 创建一个新的项目。
在“新建项目”对话框中,选择“DLL项目模板”(通常在“Visual C++” -> “Windows桌面”下)。
3. 在项目属性中,设置“配置属性” -> “常规” -> “配置类型”为“动态库(.dll)”。
4. 编写你的代码。
DLL的入口点通常是一个导出函数,例如`__declspec(dllexport) void MyFunction()`。
5. 编译项目。
编译成功后,你会得到一个DLL文件。
编译静态链接库(LIB)1. 打开Visual Studio。
2. 创建一个新的项目。
在“新建项目”对话框中,选择“静态库项目模板”(通常在“Visual C++” -> “通用”下)。
3. 编写你的代码。
LIB不要求特别的入口点,但你需要确保所有的函数和变量都被正确地声明为`__declspec(dllexport)`或`__declspec(dllimport)`。
4. 编译项目。
编译成功后,你会得到一个LIB文件和一个PDB文件。
PDB 文件包含了程序数据库信息,用于源码级别的调试。
请注意,以上步骤可能会因Visual Studio的不同版本和设置有所不同。
如果你遇到任何问题,建议查阅Visual Studio的官方文档或寻求在线帮助。
关于静态链接库(Lib)与动态链接库(DLL)静态链接库(Lib)和动态链接库(DLL)的问题困扰了我很长时间,而当中关键的问题是两者有何联系?又有何区别呢?怎么创建?怎么使用?使用的过程中要注意什么?一直想把这个问题总结一下。
在windows下一般可以看到后缀为dll和后缀为lib的文件,但这两种文件可以分为三种库,分别是动态链接库(Dyna mic-Link Libraries),目标库(Object Li braries)和导入库(Import Libra ries),下面一一解释这三种库。
目标库(Object Li braries)目标库又叫静态链接库,是扩展名为.LIB的文件,包括了用户程序要用到的各种函数。
它在用户程序进行链接时,“静态链接”到可执行程序文件当中。
例如,在V C++中最常使用到的C运行时目标库文件就是LIB C.LIB。
在链接应用程序时常使用所谓“静态链接”的方法,即将各个目标文件(.obj)、运行时函数库(.lib)以及已编译的资源文件(.res)链接到一起,形成一个可执行文件(.exe)。
使用静态链接时,可执行文件需要使用的各种函数和资源都已包含到文件中。
这样做的缺点是对于多个程序都使用的相同函数和资源要重复链接到exe文件中,使程序变大、占用内存增加。
导入库(I mport Li braries)导入库是一种特殊形式的目标库文件形式。
和目标库文件一样,导入库文件的扩展名也是.LIB,也是在用户程序被链接时,被“静态链接”到可执行文件当中。
但是不同的是,导入库文件中并不包含有程序代码。
相应的,它包含了相关的链接信息,帮助应用程序在可执行文件中建立起正确的对应于动态链接库的重定向表。
比如KERNEL32.LIB、USER32.LIB和GDI32.LIB就是我们常用到的导入库,通过它们,我们就可以调用Windows提供的函数了。
如果我们在程序中使用到了Rec tangle这个函数,GDI32.LIB就可以告诉链接器,这个函数在GDI32.DLL动态链接库文件中。
1. 什么是lib文件,lib和dll的关系如何(1)lib是编译时需要的,dll是运行时需要的。
如果要完成源代码的编译,有lib就够了。
如果也使动态连接的程序运行起来,有dll就够了。
在开发和调试阶段,当然最好都有。
(2)一般的动态库程序有lib文件和dll文件。
lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。
如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。
如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。
静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。
但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。
(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,DLL 库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行时再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。
从上面的说明可以看出,DLL和.LIB文件必须随应用程序一起发行,否则应用程序将会产生错误。
2、严重警告:(1) 用 extern "C" _declspec(dllexport) 只可以导出全局函数,不能导出类的成员函数(2) 使用extern "C" _declspec(dllexport)输出的函数可以被c语言调用,否则则不可(3) 注意标准调用约定的问题,输出与调用的函数约定应该一致,如当dll 模块的函数输出采用标准调用约定_stdcall,则调用程序的导入函数说明也要用标准约定(4) 用extern "C" _declspec(dllexport) 和 EXPOTRT导出的函数不改变函数名,可以给c++或c编写的exe调用.假如没有extern "C",导出的函数名将会改变,只能给c++编写的exe调用(5)在动态加载动态链接库函数时注意GetProcAddress(hInst,"add")中第二个参数是否为动态链接库导出的函数名,因为在生成动态库时可能会改变动态库导出函数的函数名,加上修饰符(6)dll初始化全局变量时,全局变量要放在共享数据断,并且初始化每一个变量,在StartHook函数里初始化其值,记得一进函数就初始化(7)调试时,编译器会自动查找其目录下(不含debug和release目录)的dll文件,所以dll文件应该放在主文件目录下,但生成的应用程序则只会在同一个目录下找dll(不需要lib文件),所以单纯的运行exe,不通过编译器,那就要把dll文件放在与exe相同的目录下(8)用#pragma comment(lib,"dllTest.lib")导入lib文件,不需要在设置里修改(9) dll里的指针变量不要用newDLL 调用方式DLL(动态连接库),可以分为动态调用于静态调用。
动态链接库及静态链接库(window s下的.dll .lib和li nux下的.so .a)库有动态与静态两种,动态通常用.so为后缀,静态用.a为后缀。
例如:libhel lo.so libhel lo.a 为了在同一系统中使用不同版本的库,可以在库文件名后加上版本号为后缀,例如:libhel lo.so.1.0,由于程序连接默认以.so为文件后缀名。
所以为了使用这些库,通常使用建立符号连接的方式。
ln -s libhel lo.so.1.0 libhel lo.so.1ln -s libhel lo.so.1 libhel lo.so使用库当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。
然而,对动态库而言,就不是这样。
动态库会在执行程序内留下一个标记…指明当程序执行时,首先必须载入这个库。
由于动态库节省空间,linux下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
现在假设有一个叫hel lo的程序开发包,它提供一个静态库lib hello.a 一个动态库l ibhel lo.so,一个头文件h ello.h,头文件中提供sayhe llo()这个函数/* hello.h */void sayhel lo();另外还有一些说明文档。
这一个典型的程序开发包结构1.与动态库连接linux默认的就是与动态库连接,下面这段程序testl ib.c使用hel lo库中的sayhe llo()函数/*testli b.c*/#includ e#includ eint main(){sayhel lo();return 0;}使用如下命令进行编译$gcc -c testli b.c -o testli b.o用如下命令连接:$gcc testli b.o -lhello -o testli b在连接时要注意,假设libh ello.o 和libhe llo.a都在缺省的库搜索路径下/usr/lib下,如果在其它位置要加上-L参数与与静态库连接麻烦一些,主要是参数问题。
1:神马是Dll和Lib,神马是静态链接和动态链接大家都懂的,DLL就是动态链接库,LIB是静态链接库。
DLL其实就是EXE,只不过没main。
动态链接是相对于静态链接而言的。
所谓静态链接就是把函数或过程直接链接到可执行文件中,成为可执行程序中的一部分,当多个程序调用同样的函数时,内存里就会有这个函数的多个拷贝,浪费内存资源。
而动态链接则是提供了一个函数的描述信息给可执行文件(并没有内存拷贝),当程序被夹在到内存里开始运行的时候,系统会在底层创建DLL和应用程序之间的连接关系,当执行期间需要调用DLL函数时,系统才会真正根据链接的定位信息去执行DLL中的函数代码。
在WINDOWS32系统底下,每个进程有自己的32位的线性地址空间,若一个DLL被进程使用,则该DLL首先会被调入WIN32系统的全局堆栈,然后通过内存映射文件方式映射到这个DLL的进程地址空间。
若一个DLL被多个进程调用,则每个进程都会接收到该DLL的一个映像,而非多份的拷贝。
但,在WIN16系统下,每个进程需要拥有自己的一份DLL空间,可以理解为何静态链接没啥区别。
2:DLL和LIB区别和联系。
DLL是程序在运行阶段才需要的文件。
LIB是程序编译时需要链接的文件。
DLL只有一种,其中一定是函数和过程的实现。
LIB是有两种。
若只生成LIB的话,则这个LIB是静态编译出来的,它内部包含了函数索引以及实现,这个LIB会比较大。
若生成DLL的话,则也会生成一个LIB,这个LIB和刚才那个LIB不同,它是只有函数索引,没有实现的,它很小。
但是这俩LIB依然遵循上个原则,是在编译时候是需要被链接的。
若不链接第一个LIB的话,在程序运行时会无法找到函数实现,当掉。
若不链接第二个LIB的话,在程序运行时依然会无法找到函数实现。
但第二种LIB 有一种替代方式,就是在程序里,使用LoadLibrary,GetProcAddress替代第二个LIB的功能。
动态链接库(DLL)动态链接库和静态链接库:动态链接库⼀般不能直接执⾏,⽽且它们⼀般也不接收消息。
它们是包含许多函数的独⽴⽂件,这些函数可以被应⽤程序和其他 DLL 调⽤以完成某些特定的⼯作。
⼀个动态链接库只有在另外⼀个模块调⽤其所包含的函数时才被启动。
“静态链接” ⼀般是在程序开发过程中发⽣的,⽤于把⼀些⽂件链接在⼀起创建⼀个 Windows 可执⾏⽂件。
这些⽂件包括各种各样的对象模块(.OBJ),运⾏时库⽂件(.LIB),通常还有已编译的资源⽂件(.RES)。
与其相反,动态链接则发⽣在程序运⾏时。
静态库:函数和数据被编译进⼀个⼆进制⽂件,扩展名为(.lib)。
在使⽤静态库的情况下,在编译链接可执⾏⽂件时:链接器从静态库中复制这些函数和数据,并把它们和应⽤程序的其他模块组合起来创建最终的可执⾏⽂件(.exe)。
当发布产品时,只需要发布这个可执⾏⽂件,并不需要发布被使⽤的静态库。
“动态链接” 是指 Windows 的链接过程,在这个过程中它把模块中的函数调⽤与在库模块中的实际函数链接在⼀起。
动态库:在使⽤动态库时,往往提供两个⽂件:⼀个导⼊库(.lib,⾮必须) 和⼀个(.dll)⽂件。
导⼊库和静态库本质上的区别:静态库本⾝就包含了实际执⾏代码和地址符号表等数据。
⽽对于导⼊库⽽⾔,其实际的执⾏代码位于动态库中,导⼊库只包含了地址符号表等,确保程序找到对应函数的⼀些基本地址信息。
动态链接库的标准扩展名是(.dll)。
只有扩展名为(.dll)的动态链接库才能被 Windows 操作系统⾃动加载。
如果该⽂件有另外的扩展名,则程序必须明确地⽤ LoadLibrary() 或 LoadLibraryEx() 加载相应模块。
编写动态链接库我们编写的程序都可以根据 UNICODE 标识符的定义编译成能够处理 UNICODE 或者⾮ UNICODE 字符串的程序。
在创建⼀个 DLL 时,对于任何有字符或者字符串参数的函数,它都应该包括 UNICODE 和⾮ UNICODE 两个版本。
DLL的原理范文动态链接库(Dynamic Link Library,DLL)是一种在Windows操作系统中用于存储被多个应用程序共享的程序代码和数据的可执行文件。
它们经常用于存储程序的功能模块,可以在需要时被不同的应用程序动态链接调用,从而提高了程序的复用性和可维护性。
在本文中,我们将探讨DLL的原理和工作机制。
一、DLL的原理DLL是一种包含可执行代码、数据和资源的文件,它可以由多个程序共享并在运行时被动态地加载到内存中。
DLL的原理主要是基于动态链接技术,其中包含两个主要概念:静态链接和动态链接。
1.静态链接在编译程序时,编译器会将程序中所需的函数和库文件的代码复制到可执行文件中,这个过程就称为静态链接。
这样做的好处是可以将程序和其所依赖的库文件打包成一个独立的可执行文件,使得程序的移植性更强。
但是这样也会导致可执行文件的体积变得庞大,而且每次更新库文件时都需要重新编译整个程序。
2.动态链接相比于静态链接,动态链接的原理是将程序所需的函数和数据与库文件分开存储,当程序需要调用库文件中的函数或者数据时,通过动态链接器将库文件加载到内存中,然后将程序中的函数和库文件中的函数进行链接,从而实现函数的调用。
这种方式可以减小程序的体积,提高程序的运行效率,并且使得程序可以灵活地调用不同版本的库文件。
二、DLL的工作机制DLL的工作机制主要包括DLL的加载、链接和卸载三个过程。
1.DLL的加载当程序开始运行时,操作系统会根据程序中指定的DLL文件路径,通过动态链接器将DLL文件加载到内存中。
在加载DLL文件时,动态链接器会解析DLL文件的导出表,获取DLL中所包含的函数以及函数的地址,然后将这些信息保存到程序的内存中,以备程序需要调用DLL中的函数时进行链接。
2.DLL的链接在程序需要调用DLL中的函数时,动态链接器会根据函数名在程序的内存中查找DLL导出表中对应函数的地址,并将程序中的函数调用指向DLL中的函数地址,从而实现函数的调用。
ln -S libhello.so.1.0 libhello.so.1ln -S libhello.so.1 libhello.so使用库当要使用静态的程序库时,连接器会找出程序所需的函数,然后将它们拷贝到执行文件,由于这种拷贝是完整的,所以一旦连接成功,静态程序库也就不再需要了。
然而,对动态库而言,就不是这样。
动态库会在执行程序内留下一个标记,指明当程序执行时,首先必须载入这个库。
由于动态库节省空间,linUX下进行连接的缺省操作是首先连接动态库,也就是说,如果同时存在静态和动态库,不特别指定的话,将与动态库相连接。
现在假设有一个叫hello的程序开发包,它提供一个静态库libhello.a 一个动态库libhello.so,一个头文件hello.h,头文件中提供Sayhello()这个函数/* hello.h */void Sayhello();另外还有一些说明文档。
这一个典型的程序开发包结构1. 与动态库连接]linux默认的就是与动态库连接,下面这段程序testlib.c使用hello库中的Sayhello()函数/*testlib.c*/#i nclude#i ncludeint mai n(){Sayhello();return 0;}使用如下命令进行编译$gcc -C testlib.c -o testlib.o用如下命令连接:$gcc testlib.o -lhello -o testlib在连接时要注意,假设libhello.o和libhello.a都在缺省的库搜索路径下/usr/lib下,如果在3.动态库的路径问题为了让执行程序顺利找到动态库,有三种方法:(1) 把库拷贝到∕usr∕lib和/Iib目录下。
⑵在 LD_LIBRARY_PATH 环境变量中加上库所在路径。
例如动态库IibheIlo.so 在∕home∕ting/lib目录下,以 bash为例,使用命令:|$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/ti ng/lib(3)修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。
这样,加入的目录下的所有库文件都可见、4.查看库中的符号有时候可能需要查看一个库中到底有哪些函数,nm命令可以打印出库中的涉及到的所有符号。
库既可以是静态的也可以是动态的。
nm列出的符号有很多,常见的有三种,一种是在库中被调用,但并没有在库中定义(表明需要其他库支持),用U表示;一种是库中定义的函数,用T表示,这是最常见的;另外一种是所谓的弱态”符号,它们虽然在库中被定义,但是可能被其他库中的同名符号覆盖,用W表示。
例如,假设开发者希望知道上央提到的hello库中是否定义了 Printf():$nm libhello.so |grep Printf/* hello.c */#i ncludevoid Sayhello(){Prin tf("hello,world∖n");}用gcc编绎该文件,在编绎时可以使用任何全法的编绎参数,例如-g加入调试代码等:gcc -C hello.c -o hello.o1. 连接成静态库连接成静态库使用ar命令,其实ar是archive的意思$ar CqS libhello.a hello.o2. 连接成动态库生成动态库用gcc来完成,由于可能存在多个版本,因此通常指定版本号:$gcc -Shared -Wl,-s On ame,libhello.so.1 -o libhello.so.1.0 hello.o另外再建立两个符号连接:$ln -S libhello.so.1.0 libhello.so.1$ln -S libhello.so.1 libhello.so-Wl表示后面的参数也就是-Soname,libhello.so.1 直接传给连接器ld进行处理。
实际上,每-Wl表示后面的参数也就是-Soname,libhello.so.1 直接传给连接器ld进行处理。
实际上,每便会将Soname 嵌入连结中的二进制文件内,而不是它正在运行的实际文件名, 在程序执行期间,程序会查找拥有 Soname 名字的文件,而不是库的文件名,换句话说, Soname 是库的区分标志。
这样做的目的主要是允许系统中多个版本的库文件共存, 习惯上在命名库文件的时候通常与摘要:动态链接库技术实现和设计程序常用的技术,在 WindowS 和LinUX 系统中都有动态 库的概念,采用动态库可以有效的减少程序大小, 节省空间,提高效率,增加程序的可扩展性,便于模块化管理。
但不同操作系统的动态库由于格式 不同,在需要不同操作系统调用时需要进行动态库程序移植。
本文分析和比较了两种操作系统动态库技术,并给出了将 ViSUaI C++编制的动态库移植到 LinUX 上的方法和经验。
动态库(Dynamic Link Library abbr , DLL)技术是程序设计中经常采用的技术。
其目 的减少程序的大小,节省空间,提高效率,具有很高的灵活性。
采用动态库技术对于升级软件版本更加容易。
与静态库(StatiC Link Library )不同,动态库里面的函数不是执行程序本 身的一部分,而是根据执行需要按需载入,其执行代码可以同时在多个程序中共享。
在Windows 和LinUX 操作系统中,都可采用这种方式进行软件设计,但他们的调用方 式以及程序编制方式不尽相同。
本文首先分析了在这两种操作系统中通常采用的动态库调用 方法以及程序编制方式,然后分析比较了这两种方式的不同之处,最后根据实际移植程序经验,介绍了将 VC++编制的Windows 动态库移植到LinUX 下的方法。
2、动态库技术2.1 Windows 动态库技术动态链接库是实现 Windows 应用程序共享资源、节省内存空间、提高使用效率的一个 重要技术手段。
常见的动态库包含外部函数和资源,也有一些动态库只包含资源,如 Windows 字体资源文件,称之为资源动态链接库。
通常动态库以 .dll ,.drv 、.fon 等作为后缀。
相应的 Windows 静态库通常以」ib 结尾,Windows 自己就将一些主要的系统功能以动态库模块的形式实现。
Win dows 动态库在运行时被系统加载到进程的虚拟空间中,使用从调用进程的虚拟地 址空间分配的内存,成为调用进程的一部分。
DLL 也只能被该进程的线程所访问。
DLL 的句柄可以被调用进程使用;调用进程的句柄可以被 DLL使用。
DLL模块中包含各种导出函数,用于向外界提供服务。
DLL可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个DLL在内存中只有一个实例;DLL实现了代码封装性;DLL的编制与具体的编程语言及编译器无关,可以通过DLL来实现混合语言编程。
DLL函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。
根据调用方式的不同,对动态库的调用可分为静态调用方式和动态调用方式。
(1) 静态调用,也称为隐式调用,由编译系统完成对DLL的加载和应用程序结束时DLL 卸载的编码(Windows系统负责对DLL调用次数的计数),调用方式简单,能够满足通常的一要求。
通常采用的调用方式是把产生动态连接库时产生的丄IB文件加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。
LIB文件包含了每一个 DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。
Lib文件包含的信息进入到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。
(2) 动态调用,即显式调用方式,是由编程者用 API函数加载和卸载 DLL来达到调用DLL 的目的,比较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。
在Windows系统中,与动态库调用有关的函数包括:在Windows中创建动态库也非常方便和简单。
在ViSUaI C++中,可以创建不用 MFC而直接用C语言写的DLL程序,也可以创建基于 MFC类库的DLL程序。
每一个DLL必须有一个入口点,在VC++中,DIIMain是一个缺省的入口函数。
DllMain负责初始化(InitializatiOn)和结束(Termination)工作。
动态库输出函数也有两种约定,分别是基于调用约定和名字修饰约定。
DLL程序定义的函数分为内部函数和导出函数,动态库导出的函数供其它程序模块调用。
通常可以有下面几种方法导出函数:①采用模块定义文件的EXPoRT部分指定要输入的函数或者变量。
②使用MFC提供的修饰符号_declspec(dllexport)。
③以命令行方式,采用/EXPORT命令行输出有关函数。
在Windows动态库中,有时需要编写模块定义文件(.DEF),它是用于描述 DLL属性的模块语句组成的文本文件。
2.2 LinUX共享对象技术在LinUX操作系统中,采用了很多共享对象技术( Shared ObjeCt ),虽然它和 Windows 里的动态库相对应,但它并不称为动态库。
相应的共享对象文件以.so作为后缀,为了方便,在本文中,对该概念不进行专门区分。
LinUX系统的/Iib以及标准图形界面的∕usr∕X11R6∕lib 等目录里面,就有许多以so结尾的共享对象。
同样,在LinUX下,也有静态函数库这种调用方式,相应的后缀以.a结束。
LinUX采用该共享对象技术以方便程序间共享,节省程序占有空间,增加程序的可扩展性和灵活性。
LinUX还可以通过LD-PRELOAD变量让开发人员可以使用自己的程序库中的模块来替换系统模块。
同Windows系统一样,在 LinUX中创建和使用动态库是比较容易的事情,在编译函数库源程序时加上-Shared选项即可,这样所生成的执行程序就是动态链接库。
通常这样的程序以so为后缀,在LinUX动态库程序设计过程中,通常流程是编写用户的接口文件,通常是.h文件,编写实际的函数文件,以.c或.cpp为后缀,再编写 makefile文件。
对于较小的动态库程序可以不用如此,但这样设计使程序更加合理。
编译生成动态连接库后,进而可以在程序中进行调用。
在LinUX中,可以采用多种调用方式,同 Windows的系统目录(..∖system32 等)一样,可以将动态库文件拷贝到/Iib目录或者在/lib目录里面建立符号连接,以便所有用户使用。
下面介绍LinUX调用动态库经常使用的函数,但在使用动态库时,源程序必须包含dlfcn.h头文件,该文件定义调用动态链接库的函数的原型。
(1) _ 打开动态链接库:dlopen,函数原型 void *dlopen (const Char *filename, int flag);dlopen用于打开指定名字(filename)的动态链接库,并返回操作句柄。