DLL相关的东西

1、DLL的加载方式

隐式:

#pragma comment(lib, "XX.lib");

编译器去查找名为XX.dll的DLL,除了名字相同,该DLL和该LIB的GUID也相同。

显式:

HINSTANCE   hInst = LoadLibrary(TEXT("XX.dll"));

if(NULL == hInst)  retrun;

HINSTANCE hInst = LoadLibrary(TEXT("XX.dll"), NULL,   FLAGS);

第三个参数为一些标志,详见核心编程。

2、DLL的入口函数

原型

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
);

其中hModule为该DLL在当前进程地址空间中的位置,ul_reason_for_call为调用此函数的原因,lpReserved如果为显式加载则为0,如果为隐式加载则为非0。

详细说一下ul_reason_for_call

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
#ifdef _DEBUG switch (ul_reason_for_call)
{
//只在该DLL第一次加载进地址空间的时候被调用一次
//此后当该DLL被加载进不同进程的地址空间时让然不调用
//当主调线程通过该reason调用DllMain函数时,主调线程不会收到DLL_THREAD_ATTACH通知
case DLL_PROCESS_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有新【线程创建】的时候,新创建的线程先执行此段代码
//然后再去执行线程本身的代码
//不管有几个DLL,每个DLL的此处代码都会被新线程执行
case DLL_THREAD_ATTACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_ATTACH ***********\r\n"));
break; //当该DLL已经被加载到进程地址空间后,当有【线程结束】的时候,该线程结束之前会调用此处代码
//然后才返回
//不管有几个DLL,每个DLL的此处代码都会被执行
case DLL_THREAD_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_THREAD_DETACH *********** \r\n"));
break; //只有在该DLL从内存中卸载的时候才会被调用一次
case DLL_PROCESS_DETACH:
OutputDebugString(TEXT("\r\n***********B Dll DLL_PROCESS_DETACH ***********\r\n"));
break;
} #endif return TRUE;
}

demo

有两个DLL, ADll.dll 和 BDll.dll

在程序中加载这个两个DLL, 然后创建一个新线程,看输出

//加载DLL
void CUseABDllDlg::OnBnClickedBtnLoadlib()
{
HINSTANCE hInstA = LoadLibrary(_T("ADll.dll"));
HINSTANCE HIntB = LoadLibrary(_T("BDll.dll"));
if (NULL == hInstA || NULL == HIntB)
{
AfxMessageBox(_T("加载DLL失败"));
return;
}
} //线程函数
UINT WINAPI WorkThread(LPVOID lpParam)
{
#ifdef _DEBUG
OutputDebugString(TEXT("\r\n&&&&&&&&&&&&&&&&&&线程被创建&&&&&&&&&&&&&&&&&\r\n"));
#endif return 0U;
} //创建线程
void CUseABDllDlg::OnBnClickedButton2()
{
HANDLE hThread = (HANDLE)_beginthreadex(NULL, , WorkThread, NULL, , NULL);
if (NULL == hThread || INVALID_HANDLE_VALUE == hThread)
{
AfxMessageBox(_T("创建线程失败"));
}
}

输出

结论:

每创建一个新线程,当前进程地址空间中的DLL的DllMain函数都会通过DLL_THREAD_ATTACH通知被调用一次

每结束一个线程,进程地址空间空的DLL的DllMain函数都会通过DLL_THREAD_DETACH通知被调用一次。

【windows核心编程】DLL相关(1)的更多相关文章

  1. windows核心编程 DLL技术 【转】

    注:本文章转载于网络,源地址为:http://blog.csdn.net/ithzhang/article/details/7051558 本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑 ...

  2. 《Windows核心编程系列》二十谈谈DLL高级技术

    本篇文章将介绍DLL显式链接的过程和模块基地址重定位及模块绑定的技术. 第一种将DLL映射到进程地址空间的方式是直接在源代码中引用DLL中所包含的函数或是变量,DLL在程序运行后由加载程序隐式的载入, ...

  3. 《windows核心编程系列》十九谈谈使用远程线程来注入DLL。

    windows内的各个进程有各自的地址空间.它们相互独立互不干扰保证了系统的安全性.但是windows也为调试器或是其他工具设计了一些函数,这些函数可以让一个进程对另一个进程进行操作.虽然他们是为调试 ...

  4. 《windows核心编程系列》十七谈谈dll

    DLL全称dynamic linking library.即动态链接库.广泛应用与windows及其他系统中.因此对dll的深刻了解,对计算机软件开发专业人员来说非常重要. windows中所有API ...

  5. 《Windows核心编程》读书笔记 上

    [C++]<Windows核心编程>读书笔记 这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对 ...

  6. C++Windows核心编程读书笔记

    转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%96%87/71405.shtml "C++Windows核心编程读书笔 ...

  7. 【转】《windows核心编程》读书笔记

    这篇笔记是我在读<Windows核心编程>第5版时做的记录和总结(部分章节是第4版的书),没有摘抄原句,包含了很多我个人的思考和对实现的推断,因此不少条款和Windows实际机制可能有出入 ...

  8. 《windows核心编程系列》二十一谈谈基址重定位和模块绑定

    每个DLL和可执行文件都有一个首选基地址.它表示该模块被映射到进程地址空间时最佳的内存地址.在构建可执行文件时,默认情况下链接器会将它的首选基地址设为0x400000.对于DLL来说,链接器会将它的首 ...

  9. 《windows核心编程系列》十六谈谈内存映射文件

    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟内存不同的是,内存映射文件的物理存储器来自磁盘中的文件,而非系统的页交换文件.将文件映射到内存中后,我们就可以在内存中操作他们了 ...

  10. windows核心编程 - 线程同步机制

    线程同步机制 常用的线程同步机制有很多种,主要分为用户模式和内核对象两类:其中 用户模式包括:原子操作.关键代码段 内核对象包括:时间内核对象(Event).等待定时器内核对象(WaitableTim ...

随机推荐

  1. lintcode: 三数之和II

    题目 三数之和 II 给一个包含n个整数的数组S, 找到和与给定整数target最接近的三元组,返回这三个数的和. 样例 例如S = .  和最接近1的三元组是 -1 + 2 + 1 = 2. 注意 ...

  2. yii2 学习中

    属性: public function __get($name) // 这里$name是属性名 { $getter = 'get' . $name; // getter函数的函数名 if (metho ...

  3. IntelliJ IDEA像Eclipse一样打开多个项目

    原文:http://blog.csdn.net/zht666/article/details/47831893 我们做项目实际中经常会遇到这样的情况,创建一个common项目(Maven项目)作为公用 ...

  4. 234. Palindrome Linked List

    题目: Given a singly linked list, determine if it is a palindrome. Follow up:Could you do it in O(n) t ...

  5. 【Effective c++】条款6:若不想使用编译器自动生成的函数就应该明确拒绝

    地产中介卖的是房子,其使用的中介软件系统应该有个类用来描述卖掉的房子 class HomeFoeSale { ......} 但是任何房子都是独一无二的,不应该存在两个房子拥有同样的属性,因此以下操作 ...

  6. testNG小试牛刀

    testNG是一个测试框架,其灵感来自JUnit和NUnit的,但引入了一些新的功能,使其功能更强大,使用更方便. testNG是一个开源自动化测试框架:testNG表示下一代. testNG是类似于 ...

  7. 构建linux内核源码树

    编写驱动程序时,需要内核源码树的支持.内核源码树时从内核源代码编译得到的.下面开始构造内核源代码的步骤.以Ubuntu为例子 1. 下载内源代码,位置www.kernel.org. (注意:源码树内核 ...

  8. GridView官方教程及示例

    Grid View GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The gri ...

  9. 转 intent常用功能

    1.从google搜索内容Intent intent = new Intent();intent.setAction(Intent.ACTION_WEB_SEARCH);intent.putExtra ...

  10. linux系统设置服务开机启动3种方法,Linux开机启动程序详解

    linux系统设置服务开机启动 方法1:.利用ntsysv伪图形进行设置,利用root登陆 终端命令下输入ntsysv 回车:如下图     方法2:利用命令行chkconfig命令进行设置 简要说明 ...