动态链接库简介(Windows)

it2025-08-22  3

 

简介

DLL提供了一种模块化应用程序的方法,以更容易地更新和重用所定义的功能。当几个应用程序同时使用相同的功能时,DLL还有助于减少内存开销,因为尽管每个应用程序都收到自己的DLL数据副本,但应用程序共享DLL代码。因此,操作系统和程序加载速度更快,运行速度更快,占用计算机上的磁盘空间更少。

通过使用DLL,一个程序可以被模块化成独立的组件,按需加载和更新。举个例子,在Windows操作系统中,Comdlg32.dll用于执行对话框相关功能。每个程序都可以使用DLL中包含的功能,来打开一个对话框,这极大的促进了代码的重用和有效的内存使用。当需要升级Comdlg32.dll时,只需要替换这个文件即可。即更新更容易应用到每个模块,而不会影响程序的其他部分。

与动态链接相对的,还有一个静态链接。所谓静态链接是指把要调用的函数或者过程链接到可执行文件中,成为可执行文件的一部分。两者的关系如下图:

DLL分类

隐式加载(Load-time Dynamic)

在加载时动态链接中,应用程序像调用本地函数一样,可以直接调用导出的DLL函数。要使用加载时动态链接,在编译和链接阶段需要提供一个头文件(.h)和一个导入库(.lib)文件。链接器将向系统提供加载DLL所需的信息,通过这个lib文件的信息在需要的时候加载DLL函数位置。

显示加载(Run-time Dynamic)

应用程序在运行时,调用LoadLibrary函数或LoadLibraryEx函数来加载DLL,并获取其Handle。成功加载DLL之后,使用GetProcAddress函数获取要调用的导出DLL函数的地址,此时不需要导入库文件(.lib)。

不得不吐槽,还是英文版的名称更加的直接了当,变成中文后又是另一种味道了。

下是图是使用DLL Export Viewer软件对DLL进行扫查的结果,可以看到对于我们常用的网络编程库wsock32.dll中,有一个bind的函数,其函数的偏移地址是0x52e83975,还有一个相对偏移地址0x00003975。前面是动态加载到程序后的地址,后面是加载前函数所在的地址。

相关加载函数

如果搜索成功,系统将DLL模块映射到进程的虚拟地址空间,并增加引用计数。如果对LoadLibrary或LoadLibraryEx的调用指定了一个DLL,该DLL的代码已经映射到调用进程的虚拟地址空间中,该函数只返回DLL的句柄并增加DLL引用计数。注意,两个具有相同基本文件名和扩展名,但目录不同的DLL,系统会当做不相同的DLL处理。

HMODULE LoadLibraryA( LPCSTR lpLibFileName ); HMODULE LoadLibraryExA( LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags );

进程使用GetProcAddress来获取DLL中导出函数的地址,使用LoadLibrary或LoadLibraryEx返回的句柄。当不使用时,调用FreeLibrary将句柄进行释放。

运行时动态链接(Run-time dynamic link)使进程能够在DLL不可用的情况下继续运行。例如,如果一个进程无法找到一个DLL,通过返回的NULL,可以尝试使用另一个DLL,或者它可以通知调用者一个错误。

FARPROC GetProcAddress( HMODULE hModule, LPCSTR lpProcName ); BOOL FreeLibrary( HMODULE hLibModule );

 参考链接:

1. About Dynamic-Link Libraries——MSDN(强烈推荐看原版!)

2. 编译-编译原理C/C++ 静态链接库(.a) 与 动态链接库(.so)

3. 动态链接库与静态链接库的区别

 

最新回复(0)