天天看点

DLL的入口点函数

一、基本介绍

系统在不同的时候调用这个入口点函数,这些调用是通知性质的,

用来执行一些与进程或者线程有关的清理工作。如果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

的通知之后,操作系统才会真正地终止进程