DLL入口函数DllMain

转载 2016年05月30日 22:40:40

每个DLL都可以有一个入口点函数DllMain,系统会在不同的时刻调用此函数。以下是DllMain的一般形式:

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

以上代码摘自MSDN,几乎所有的DllMain都以这种形式呈现。
先来看一下这个函数传递进来的参数:
1、 HINSTANCE hinstDLL
这个参数是该DLL实例的句柄,也就是此DLL映射到进程地址空间后,在该进程地址空间中的位置。
2、 DWORD fdwReason
此参数标示了调用DllMain函数的原因。有四种值,就是函数中case后的取值。各个取值的含义,稍后论述。
3、 LPVOID lpReserved
保留。

现在我们来讨论一下fdwReason的四种取值,这些取值,也直接反映了操作系统会在何种情况下调用DllMain。
1、DLL_PROCESS_ATTACH
当系统第一次将一个DLL映射到进程地址空间中时,会调用DllMain,并为fdwReason传入DLL_PROCESS_ATTACH。

注意,只有在第一次映射的时候,才会这样。如之后,另一线程再次显式加载此DLL,则操作系统只是增加该DLL的使用计数,而不会再次使用DLL_PROCESS_ATTACH来调用DllMain。

对DLL_PROCESS_ATTACH的处理,代表了DLL的初始化。

DllMain的返回值,也是针对DLL_PROCESS_ATTACH消息的。对于其余的三种取值,不起作用。

对于隐式加载,如DllMain返回FALSE,则程序会启动失败。对于显式加载,则会使LoadLibrary返回NULL。

2、DLL_PROCESS_DETACH
当系统将一个DLL从进程地址空间中撤销映射时,则会向DllMain传入DLL_PROCESS_DETACH。我们应当在此处放置一些清理代码。

当使用FreeLibrary时,如该线程的使用计数为0时,操作系统才会使用DLL_PROCESS_DETACH来调用DllMain。如使用计数大于0,则只是单纯的减少该DLL的计数。

3、DLL_THREAD_ATTACH
当进程创建一个线程,则系统会检查当前已映射到该进程空间中的所有DLL映像,并用DLL_THREAD_ATTACH来调用每个DLL的DllMain。

只有当所有DLL都完成了对DLL_THREAD_ATTACH的处理后,新线程才会执行它的线程函数。

另外,主线程不可能用DLL_THREAD_ATTACH来调用DllMain,因为主线程必然是在进程初始化的时候,用DLL_PROCESS_ATTACH调用DllMain的。

4、DLL_THREAD_DETACH
线程若要终止,会调用ExitThread,但是此函数不会立即终止线程,而是会利用DLL_THREAD_DETACH来调用当前进程地址空间中的所有DLL镜像的DllMain.
当每个DLL的DllMain都处理完后,系统才会真正的结束线程。

最后看一下DllMain的序列化调用

举个例子:
进程中有两个线程,A与B。进程的地址空间中,映射了一个名为SomeDll.dll的DLL。两个线程都准备通过CreateThread来创建另两个线程,C和D。

当线程A调用CreateThread来创建线程C的时候,系统会用DLL_THREAD_ATTACH来调用SomeDll.dll的DllMain,当线程C执行其中代码的时候,线程B调用CreateThread来创建线程D。

这时,系统同样会用DLL_THREAD_ATTACH来调用SomeDll.dll的DllMain,这次是让线程D来执行其中的代码。

但是此时,系统会对DllMain执行序列化,它会将线程D挂起,直至线程C执行完DllMain中的代码返回为止。

当C线程执行完DllMain中的代码并返回时,可以继续执行C的线程函数。此时,系统会唤醒线程D,让D执行DllMain中的代码。当返回后,线程D开始执行线程函数。

C++ 生成dll的入口函数

dll的入口函数,简而言之,就是只在dll被load的时候调用一次,之后都不会被调用,也无法在dll外部被调用。 并且同一个dll,被多个进程load多次,内存中也只会有此动态链接库的一个副本,也只...
  • hust_bochu_xuchao
  • hust_bochu_xuchao
  • 2016年11月02日 14:52
  • 1145

Dll入口函数参数详解...

DLL程序入口点函数:DllMain,注意:大小写是区别的(仅导出资源的DLL可以没有DllMain函数)。 函数原型: BOOL APIENTRY DllMain( HMODULE hModul...
  • friendan
  • friendan
  • 2012年06月13日 13:52
  • 16792

动态链接库(DLL)入口/出口点

链接库入口/出口点当动态链接库首次启动和结束时,我们呼叫了DllMain函数。DllMain的第一个参数是链接库的执行实体句柄。如果您的链接库使用需要执行实体句柄(诸如DialogBox)的资源,那么...
  • jjunjoe
  • jjunjoe
  • 2011年03月02日 09:59
  • 3214

dll动态链接库(2)---入口函数DllMain

1、动态库导出函数的查看: 使用Vc++自带的Depends工具进行查看,但是只能看到函数的名字,具体的函数参数及返回值看不到,所以要把动态库导出函数声明的头文件(.h文件)打包给> 。 ...
  • u011036348
  • u011036348
  • 2013年09月02日 19:54
  • 1689

DLL入口函数DllMain

 BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)DllMain简介    跟e...
  • formerman
  • formerman
  • 2009年07月12日 10:58
  • 7942

动态连接库入口点函数

  DLL可以制定一个入口点函数,如果指定了入口点函数,系统在进程或线程载入或卸载DLL时就会调用入口点函数。这可以用来实现简单的初始化及清除任务。例如,新的线程创建时,可以设立线程局部存储器,然后线...
  • dtdn
  • dtdn
  • 2005年03月01日 17:22
  • 5959

DLL入口函数DllMain

每个DLL都可以有一个入口点函数DllMain,系统会在不同的时刻调用此函数。以下是DllMain的一般形式:BOOL WINAPI DllMain( HINSTANCE hinstDLL,...
  • birdflyto206
  • birdflyto206
  • 2016年05月30日 22:40
  • 508

C#直接使用DllImport外部Dll的方法

C#.Net调用基本格式: [DLLImport(“DLL文件路径”)] 修饰符 extern 返回值类型 方法名称(参数列表) 如: [DllImport("kernel32.dll", Se...
  • u011981242
  • u011981242
  • 2016年09月22日 14:54
  • 23995

如何在MFC DLL工程添加DllMain入口

今天碰巧看到有人问了这个问题. 他使用的是MFC DLL,但是却想添加DllMain作为入口函数,但是很明显直接编译肯定编不过.所以我在这里介绍一个通过编译的简单方法: 右键 -> 项目属性 -> 配...
  • jwybobo2007
  • jwybobo2007
  • 2011年03月13日 22:15
  • 3560

DLLMain的入口函数不能创建新线程

微软官方有解释: PRB: Cannot Create an MFC Thread During DLL Startup SYMPTOMS An MFC DLL that creat...
  • a949308398
  • a949308398
  • 2014年11月13日 21:42
  • 480
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DLL入口函数DllMain
举报原因:
原因补充:

(最多只允许输入30个字)