DllMain详解
1 DLL的进?退出函?/p>
1.1 DllMain?/p>
跟exe有个main或者WinMain入口函数一PDLL也有一个入口函敎ͼ是DllMain。以“DllMain”为关键字Q来看看MSDN帮助文档怎么介绍q个函数的?/p>
The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(要翻译:(x)对于动态链接库QDllMain是一个可选的入口函数。)q句话很重要Q很多初学者可能都认ؓ(f)一个动态链接库肯定要有 DllMain函数。其实不?dng)像很多仅仅包含资源信息的DLL是没有DllMain函数的?/p>
1.2 何时调用DllMain
pȝ是在什么时候调用DllMain函数的呢Q静态链接时Q或动态链接时调用LoadLibrary和FreeLibrary都会(x)调用DllMain函数。DllMain的第三个参数fdwReason指明了系l调用Dll的原因,它可能是:
DLL_PROCESS_ATTACH?/font>
DLL_PROCESS_DETACH?/font>
DLL_THREAD_ATTACH
DLL_THREAD_DETACH?/font>
以下从这四种情况来分析系l何时调用了DllMain?nbsp;
1.2.1 DLL_PROCESS_ATTACH
大家都知道,一个程序要调用Dll里的函数Q首先要先把DLL文g映射到进E的地址I间。要把一个DLL文g映射到进E的地址I间Q有两种Ҏ(gu)Q静态链接和动态链接的LoadLibrary或者LoadLibraryEx?/p>
当一个DLL文g被映到q程的地址I间Ӟpȝ调用该DLL的DllMain函数Q传递的fdwReason参数? DLL_PROCESS_ATTACH。这U调用只?x)发生在W一ơ映时。如果同一个进E后来ؓ(f)已经映射q来的DLL再次调用LoadLibrary或? LoadLibraryExQ操作系l只?x)增加DLL的用次敎ͼ它不?x)再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不? q程用LoadLibrary同一个DLLӞ每个q程的第一ơ映都?x)用DLL_PROCESS_ATTACH调用DLL的DllMain函数?/p>
可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数?/p>
1.2.2 DLL_PROCESS_DETACH
当DLL被从q程的地址I间解除映射Ӟpȝ调用了它的DllMainQ传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时Q它应该执行q程相关的清理工作?/p>
那么什么时候DLL被从q程的地址I间解除映射呢?两种情况Q?/p>
◆FreeLibrary解除DLL映射Q?font color="#ff0000">有几个LoadLibraryQ就要有几个FreeLibraryQ?/p>
◆进E结束而解除DLL映射Q在q程l束前还没有解除DLL的映,q程l束后会(x)解除DLL映射。(如果q程的终l是因ؓ(f)调用? TerminateProcessQ系l就不会(x)用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这意味着DLL在进E结束前 没有Z(x)执行M清理工作。)
注意Q当用DLL_PROCESS_ATTACH调用DLL的DllMain函数Ӟ如果q回FALSEQ说明没有初始化成功Q系l仍?x)用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须保清理那些没有成功初始化的东西?/font>
可参考DllMainTest的DLL_PROCESS_DETACH_Test函数?/p>
1.2.3 DLL_THREAD_ATTACH
当进E创ZU程Ӟpȝ查看当前映射到进E地址I间中的所有DLL文g映像Qƈ用值DLL_THREAD_ATTACH调用DLL的DllMain函数?/p>
新创建的U程负责执行q次的DLL的DllMain函数Q只有当所有的DLL都处理完q一通知后,pȝ才允许进E开始执行它的线E函数?/p>
注意跟DLL_PROCESS_ATTACH的区别,我们在前面说q,W? n(n>=2)ơ以后地把DLL映像文g映射到进E的地址I间Ӟ是不再用DLL_PROCESS_ATTACH调用DllMain的。? DLL_THREAD_ATTACH不同Q进E中的每ơ徏立线E,都会(x)用值DLL_THREAD_ATTACH调用DllMain函数Q哪怕是U程中徏? U程也一栗?/p>
1.2.4 DLL_THREAD_DETACH
如果U程调用了ExitThread来结束线E(U程函数q回Ӟpȝ也会(x)自动调用ExitThreadQ,pȝ查看当前映射到进E空间中的所有DLL? 件映像,q用DLL_THREAD_DETACH来调用DllMain函数Q通知所有的DLLL行线E的清理工作?/p>
注意Q如果线E的l束是因为系l中的一个线E调用了TerminateThreadQ系l就不会(x)用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数?/p>
1.3 为DllMain换名
在早期的SDK版本中,DllMain是叫做DllEntryPoint。其实有一仉Zh 知的事:(x)一个Dll的入口函数名是可以自己定义的。下面我以VC++6.0Z来演C如何更攏V首先要说明一点,虽然DllMain可以换成其他函数 名,但函数的参数和返回值必dDllMain一栗而且q个函数要ؓ(f)__stdcallcdQDllMain本n也是__stdcallcdQ?/p>
打开VC++菜单Project"Settings"Link tab" Output in the Category boxQ如下图Q在Entry-point symbol中输入要替换DllMain的函数名Q当然这个函数名是你E序中已l实现的函数Q。Entry-point symbol是干么的呢?可以以关键字“Entry-point symbol”搜烦(ch)MSDN帮助文档查看Q搜索时Q打?#8220;仅搜索标?#8221;?x)更快定位?/p>
按OK后,如果马上~译的话?x)出现如下错误?x)
LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals
打开VC++菜单Project"Settings"C/C++选项卡,如下图,? Project OptionsQ末地方d”/D”Q图中蓝色高亮的地方Q,要注意位|,我试了,要把/D攑ֈ/GZ后面也会(x)链接错误Q我也不懂ؓ(f)什么,^_^。按 OKQ再ơ编译,成功。大家可以自己测试下到底有没有更Ҏ(gu)功,什么,如果试Q打式信息啊?/p>
1.4 DisableThreadLibraryCalls
看帮助就知道它是q么用的Q?/p>
The DisableThreadLibraryCalls function
disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for
the dynamic-link library (DLL) specified by hLibModule. This can reduce
the size of the working co
转自:http://blog.csdn.net/benkaoya/archive/2008/06/02/2504781.aspx