DllMain的执行线程

DllMain的执行线程

DllMain()有4个通知:

DLL_PROCESS_ATTACH

DLL_THREAD_ATTACH

DLL_THREAD_DETACH

DLL_PROCESS_DETACH

其中:DLL_PROCESS_ATTACH/DLL_PROCESS_DETACH由主线程执行

DLL_THREAD_ATTACH由新建线程执行,DLL_PROCESS_DETACH由消亡线程执行

  

对于隐式加载的DLL来说,应用程序会在执行main函数前加载DLL,执行main函数后卸载DLL。其过程如下:

1)应用程序主线程执行DllMain(),通知DLL_PROCESS_ATTACH

2)应用程序主线程执行main()

3)程序中新建线程,为已加载的DLL执行DllMain(),通知DLL_THREAD_ATTACH

4)线程执行线程函数

5)线程退出线程函数

6)线程为已加载的DLL执行DllMain(),通知DLL_THREAD_DETACH

7)应用程序主线程退出main()

8)应用程序主线程执行DllMain(),通知DLL_PROCESS_DETACH

  

测试代码:

一个DLL工程,导出一个函数void Foo(); 
// dllmain.cpp : 定义DLL 应用程序的入口点。
#include "stdafx.h"
#include <tchar.h>
#include <stdio.h>

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    const int kBuffLen = 256;
    TCHAR szLog[kBuffLen];
    DWORD dwThreadId = ::GetCurrentThreadId();
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        {
            _stprintf_s(szLog, kBuffLen, _T("[DLL] Thread(%d) execute DLL_PROCESS_ATTACH\n"), dwThreadId);
            OutputDebugString(szLog);
        }
        break;
    case DLL_THREAD_ATTACH:
        {
            _stprintf_s(szLog, kBuffLen, _T("[DLL] Thread(%d) execute DLL_THREAD_ATTACH\n"), dwThreadId);
            OutputDebugString(szLog);
        }
        break;
    case DLL_THREAD_DETACH:
        {
            _stprintf_s(szLog, kBuffLen, _T("[DLL] Thread(%d) execute DLL_THREAD_DETACH\n"), dwThreadId);
            OutputDebugString(szLog);
        }
        break;
    case DLL_PROCESS_DETACH:
        {
            _stprintf_s(szLog, kBuffLen, _T("[DLL] Thread(%d) execute DLL_PROCESS_DETACH\n"), dwThreadId);
            OutputDebugString(szLog);
        }
        break;
    }
    return TRUE;
}
   

应用程序工程,包含DLL的lib库,引用Foo() 

/*
    验证一下DllMain()的执行线程
    验证结果:
        DLL_PROCESS_ATTACH/DLL_PROCESS_DETACH由主线程执行
        DLL_THREAD_ATTACH/DLL_THREAD_DETACH由创建和消亡的线程执行   
 
*/
#include <Windows.h>
#include <tchar.h>

#pragma comment(lib, "../Debug/DLLMainDLL.lib")

void Foo();
void Bar()
{
    // 调用一下DLL的函数,使DLL链接进EXE的import table
    Foo();
}


DWORD WINAPI ThreadFunc(LPVOID lpParam)
{
    const int kBuffLen = 256;
    TCHAR szLog[kBuffLen];
    _stprintf_s(szLog, kBuffLen, _T("[EXE] Thread(%d) execute ThreadFunc()\n"), ::GetCurrentThreadId());
    OutputDebugString(szLog);

    ::Sleep(500);

    _stprintf_s(szLog, kBuffLen, _T("[EXE] Thread(%d) exit ThreadFunc()\n"), ::GetCurrentThreadId());
    OutputDebugString(szLog);

    return 0;
}

int _tmain()
{
    const int kBuffLen = 256;
    TCHAR szLog[kBuffLen];
    
    // 主线程
    DWORD dwMainThreadId = ::GetCurrentThreadId();   
    _stprintf_s(szLog, kBuffLen, _T("[EXE] MainThread(%d) execute main()\n"), dwMainThreadId);
    OutputDebugString(szLog);    

    // 新建线程
    HANDLE hThread = NULL;
    DWORD dwThreadId = 0;
    hThread = ::CreateThread(NULL, 0, ThreadFunc, NULL, 0, &dwThreadId);
    _stprintf_s(szLog, kBuffLen, _T("[EXE] Create a new thread(%d)\n"), dwThreadId);
    OutputDebugString(szLog);

    ::WaitForSingleObject(hThread, INFINITE);
    ::CloseHandle(hThread);
    hThread = NULL;

    _stprintf_s(szLog, kBuffLen, _T("[EXE] Thread(%d) is destroyed\n"), dwThreadId);
    OutputDebugString(szLog);

    ::Sleep(500);

    _stprintf_s(szLog, kBuffLen, _T("[EXE] MainThread(%d) exit main()\n"), dwMainThreadId);
    OutputDebugString(szLog);

    return 0;
}

 

执行结果:

在VC的控制台输出:    
    [DLL] Thread(1644) execute DLL_PROCESS_ATTACH
    [EXE] MainThread(1644) execute main()
    [EXE] Create a new thread(5816)
    [DLL] Thread(5816) execute DLL_THREAD_ATTACH
    [EXE] Thread(5816) execute ThreadFunc()
    [EXE] Thread(5816) exit ThreadFunc()
    [DLL] Thread(5816) execute DLL_THREAD_DETACH
    [EXE] Thread(5816) is destroyed
    [EXE] MainThread(1644) exit main()
    [DLL] Thread(1644) execute DLL_PROCESS_DETACH 
 
结果分析: 
1)应用程序主线程执行DllMain(),通知DLL_PROCESS_ATTACH
[DLL] Thread(1644) execute DLL_PROCESS_ATTACH
  
2)应用程序主线程执行main()
[EXE] MainThread(1644) execute main() 
 
3)程序中新建线程,为已加载的DLL执行DllMain(),通知DLL_THREAD_ATTACH
[EXE] Create a new thread(5816)
[DLL] Thread(5816) execute DLL_THREAD_ATTACH 
 
4)线程执行线程函数
[EXE] Thread(5816) execute ThreadFunc() 
 
5)线程退出线程函数
[EXE] Thread(5816) exit ThreadFunc() 
 
6)线程为已加载的DLL执行DllMain(),通知DLL_THREAD_DETACH
[DLL] Thread(5816) execute DLL_THREAD_DETACH
[EXE] Thread(5816) is destroyed
  
7)应用程序主线程退出main()
[EXE] MainThread(1644) exit main() 
 
8)应用程序主线程执行DllMain(),通知DLL_PROCESS_DETACH
[DLL] Thread(1644) execute DLL_PROCESS_DETACH 

 

posted @ 2014-04-18 17:22  shokey520  阅读(1143)  评论(0编辑  收藏  举报