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;
}
#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;
}
验证一下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
It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity. We had everything before us, we had nothing before us.
这是最好的时代,这是最坏的时代;这是智慧的年代,这是愚蠢的年代;这是信仰的时期,这是怀疑的时期;我们的前途拥有一切,我们的前途一无所有。
这是最好的时代,这是最坏的时代;这是智慧的年代,这是愚蠢的年代;这是信仰的时期,这是怀疑的时期;我们的前途拥有一切,我们的前途一无所有。