零、概述
·Dll文件:只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将
它们装载到内存空间中。通常映射到进程虚拟空间的同一地址上
·Dll的组成:全局数据、服务函数和资源
·导出函数,用于向外界提供服务
Windows在加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配
·DLL模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。
一、导出和导入函数的匹配
·导出函数表。导出函数由它们的符号名和称为标识号的整数与外界联系起来。
函数表中还包含了DLL中函数的地址
·动态链接过程在加载的DLL模块时动态建立一个函数调用与函数地址的对应表
·一个特殊的DLL可以既有导入函数,又有导入函数。
·声明导出函数:
__declspec(dllexport) int MyFunction(int n);
·声明输入函数:
__declspec(dllimport) int MyFuncition(int n);
·仅有导入和导出声明并不能使应用程序内部的函数调用链接到相应的DLL文件上。
应用程序的项目必须为链接程序指定所需的输入库(LIB文件)。
#pragma comment(lib,"MyDll.lib")
二、与DLL模块建立连接
·隐式链接--在应用程序中不需指明DLL文件的实际存储路径
·显式链接--与隐式连接相反
·隐式链接:
·建立一个DLL文件时,链接程序会自动生成一个与之对应的LIB导入文件。
·LIB文件包含了每一个DLL导出函数的符号名和可选的标识号
·LIB文件作为DLL的替代文件被编译到应用程序项目中
·当程序员通过静态链接方式编译生成应用程序时,
应用程序中的调用函数与LIB文件中导出符号相匹配,
这些符号或标识号进入到生成的EXE文件中。
·LIB文件中也包含了对应的DLL文件名(但不是完全的路径名),
链接程序将其存储在EXE文件内部。
·当应用程序运行过程中需要加载DLL文件时,
Windows根据这些信息发现并加载DLL,
然后通过符号名或标识号实现对DLL函数的动态链接。
·显式连接:
·直接调用Win32的LoadLibary函数,并指定DLL的路径作为参数。
·LoadLibary返回HINSTANCE参数,应用程序在调用GetProcAddress函数时使用这一参数。
·GetProcAddress函数将符号名或标识号转换为DLL内部的地址。
·在隐式链接方式中,
所有被应用程序调用的DLL文件都会在应用程序EXE文件加载时被加载在到内存中;
·在显式链接方式中,
程序员可以决定DLL文件何时加载或不加载。显式链接在运行时决定加载哪个DLL文件。
三、使用符号名连接与标识号连接
·采用标识号链接的应用程序的EXE文件体相对较小,
因为它不必包含导入函数的长字符串符号名。
四、DllMain函数
·DllMain函数是DLL模块的默认入口点。当Windows加载DLL模块时调用这一函数。
·系统首先调用全局对象的构造函数,然后调用全局函数DLLMain。
·DLLMain函数不仅在将DLL链接加载到进程时被调用,
在DLL模块与进程分离时(以及其它时候)也被调用。
五、模块句柄
·进程中的每个DLL模块被全局唯一的32字节的HINSTANCE句柄标识。
进程自己还有一个HINSTANCE句柄。
·所有这些模块句柄都只有在特定的进程内部有效,
它们代表了DLL或EXE模块在进程虚拟空间中的起始地址。
·在Win32中,HINSTANCE和HMODULE的值是相同的,这个两种类型可以替换使用
·进程模块句柄几乎总是等于0x400000,而DLL模块的加载地址的缺省句柄是0x10000000。
·如果程序同时使用了几个DLL模块,每一个都会有不同的HINSTANCE值。
这是因为在创建DLL文件时指定了不同的基地址,或者是因为加载程序
对DLL代码进行了重定位。
·模块句柄对于加载资源特别重要。Win32 的FindResource函数中带有一个HINSTANCE参数。
·EXE和DLL都有其自己的资源。
如果应用程序需要来自于DLL的资源,就将此参数指定为DLL的模块句柄。
如果需要EXE文件中包含的资源,就指定EXE的模块句柄。
·怎样得到句柄?
如果需要得到EXE模块句柄,调用带有Null参数的Win32函数GetModuleHandle;
如果需要DLL模块句柄,就调用以DLL文件名为参数的Win32函数GetModuleHandle。
六、应用程序怎样找到DLL文件
·如果应用程序使用LoadLibrary显式链接,
那么在这个函数的参数中可以指定DLL文件的完整路径。
·如果不指定路径,或是进行隐式链接,Windows将遵循下面的搜索顺序来定位DLL:
1.包含EXE文件的目录,
2.进程的当前工作目录,
3.Windows系统目录,
4.Windows目录,
5.列在Path环境变量中的一系列目录。