动态链接库DLL

《Windows核心编程》 第IV部分 动态链接库

第20章,DLL高级技术

问题一:动态加载DLL时,SetDllDirectory的作用

正常情况下, 一个可执行模块LoadLibrary单独一个DLL,没有任何问题;但如果该DLL还依赖于其他DLL模块,且和可执行模块不在同一级目录下,那么直接调用LoadLibrary会返回错误“找不到该DLL” ;

这种应用常见于集成使用其他公司提供的某功能模块,这个功能模块有一个主DLL和其他依赖DLL;如果我们把这些DLL都放在我们应用系统的根目录下,会显得很杂乱,且对以后的版本更新和维护带来很多问题,所以通常我们会将这些DLL存放在固定目录下;然后应用程序动态加载这些DLL模块。

这时候,我们就需要使用SetDllDirectory来通知应用程序,从指定目录动态加载DLL,这就是该函数的作用。

实际应用中,还遇到过一个可执行模块的两个线程,分别调用SetDllDirectory来加载不同目录下的DLL模块,很遗憾,这样做的结果是可执行模块在实际运行时崩溃。所以我们要避免在同一个进程中调用两次SetDllDirectory。

问题二:DllMain入口点函数,如何使用四个参数

在使用VS创建一个WIN32 DLL模块时,VS会自动生成带有DllMain的代码模块,如下:

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

1. DLL_PROCESS_ATTACH:

只有当DLL文件影像第一次被映射到进程地址空间时,才会调用DllMain传入此参数;如果进程中其他模块再次调用该DLL,则不会再使用该参数调用DllMain。

2. DLL_PROCESS_DETACH

当系统将一个DLL从进程地址 空间撤销时,会调用DllMain传入此参数;DLL在处理此参数时,应执行相关的清理工作。

终止进程时,调用ExitProcess 会传入此参数调用DllMain;如果调用FreeLibrary ,DllMain在DLL_PROCESS_DETACH返回之前,线程不会返回。 

3. DLL_THREAD_ATTACH

当进程创建一个线程时,系统会检查当前映射到该进程地址空间的所有DLL文件,并用该参数调用每一个DLL的DllMain函数。(每创建一个线程,就会向进程加载的所有DLL传入此参数)

比如一个进程中有两个线程:线程A和线程B,进程加载了一个名为SomeDLL.dll的模块。两个线程都准备调用CreateThread函数来创建另外两个线程:线程C和线程D。

则线程A创建线程C时,系统会用DLL_THREAD_ATTACH来调用SomeDLL.dll的DllMain函数;线程B创建线程D时,会再次用DLL_THREAD_ATTACH来调用DllMain(若线程C没有执行完DllMain中的代码,则DllMain收到第二次DLL_THREAD_ATTACH时会挂起等待,直到线程C执行完)

4. DLL_THREAD_DETACH

线程终止的首选方式是让线程函数返回,系统调用ExitThread来终止线程,但不是立即终止线程,而是会用DLL_THREAD_DETACH调用所有已加载的DLL的DllMain,通知DLL执行与线程相关的清理工作。如果是调用TerminateThread,那么系统不会用该参数调用DllMain

问题三:DllMain和 全局/静态变量的先后关系

DLL映射到进程地址空间时,先调用_DllMainCRTStartup函数,该函数会初始化C++运行库,并确保在收到DLL_PROCESS_ATTACH通知的时候,所有全局或静态C+对象都已构造完毕。也就是说,先初始化全局变量或调用全局对象的构造函数,再调用DllMain函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值