一、基本介绍
系统在不同的时候调用这个入口点函数,这些调用是通知性质的,
用来执行一些与进程或者线程有关的清理工作。如果DLL需要这些通知,则需要在源代码
中实现这个入口点函数。
注意函数名区分大小写 DllMain
函数原型
BOOL WINAPI DllMain(
In HINSTANCE hinstDLL,
In DWORD fdwReason,
In LPVOID lpvReserved
);hinstDLL 是包含这个DLL实例的句柄
fdwReason 调用函数入口点的原因,后面详细介绍
lpvReserved:为零表示隐式载入,不为零表示显示载入
注意:
为了避免产生循环依赖,Dllmain中,避免调用从其他dll中导入的函数,以及LoadLibrary(Ex),和Freelibrary
套接字函数,COM、ODBC等
另外,如果创建全局或者静态C++对象,也会存在同样的问题,因为这些对象的构造函数和析构函数也会被调用
二、相关参数
1、DLL_PROCESS_ATTACH 通知
当系统第一次将一个DLL映射到进程的地址空间中的时候,会调用DllMain,并且传入1、DLL_PROCESS_ATTACH,
之后线程再调用LoadLibrary的时候,只是递增这个DLL的引用计数,不会再传入DLL_PROCESS_ATTACH来调用DllMain函数
DLL处理DLL_PROCESS_ATTACH的时候,根据需要进行初始化
关于返回值,如果传入参数是(DLL_THREAD_ATTACH或者DLL_THREAD_DETACH)的时候,系统将忽略DllMain返回值
关于程序调用,如果隐式调用失败,系统直接无法启动
在显示调用中,如果DLLMain函数返回为false,也就是初始化不成功,系统会从进程地址空间中撤销对DLL的映射,并让LoadLibrary返回NULL
2、DLL_PROCESS_DETACH 通知
当系统将一个DLL从进程的地址空间中撤销映射时,会调用DLL的DLLMain函数,并传入参数DLL_PROCESS_DETACH 。
DLL处理这个通知的时候,应该执行与进程相关的清理工作,比如调用HeapDestory来销毁堆。
撤销映射有两种方式,1、进程终止,2、某个线程调用了FreeLibrary或者FreeLibraryAndExitThread,如果调用的FreeLibrary,那么在
DLLMain处理完 DLL_PROCESS_DETACH通知之前,线程不会从调用中返回
需要注意的时候,DLL可能会阻碍进程的终止,当DLLMain收到DLL_PROCESS_DETACH通知的时候,只有每个DLL都处理完DLL_PROCESS_DETACH
的通知之后,操作系统才会真正地终止进程