DllMain详解

C++-dllmain介绍 dllmain 百度解释的很清楚 跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain,对于动态链接库,DllMain是一个可选的入口函数 入口函数定义 BOOL WINAPI DllMain( _In_ HINSTANCE hinstDLL, // 指向自身的句柄 _In_ DWORD fdwReason, // 调用原因 _In_ LPVOID lpvReserved // 隐式加载和显式加载 ); 系统在调用LoadLibrary和Fre 阅读详情

DllMain详解

转载自:http://blog.youkuaiyun.com/benkaoya/archive/2008/06/02/2504781.aspx

1  DLL的进入/退出函数

1.1  DllMain简介

跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。以“DllMain”为关键字,来看看MSDN帮助文档怎么介绍这个函数的。

The DllMain function is an optional method of entry into a dynamic-link library (DLL)。(简要翻译:对于一个Dll模块,DllMain函数是可选的。)这句话很重要,很多初学者可能都认为一个动态链接库肯定要有DllMain函数。其实不然,像很多仅仅包含资源信息的DLL是没有DllMain函数的。

1.2 何时调用DllMain

系统是在什么时候调用DllMain函数的呢?静态链接时,或动态链接时调用 LoadLibrary和FreeLibrary都会调用DllMain函数。DllMain的第三个参数fdwReason指明了系统调用Dll的原因,它可能是DLL_PROCESS_ATTACH、DLL_PROCESS_DETACH、DLL_THREAD_ATTACH和 DLL_THREAD_DETACH。以下从这四种情况来分析系统何时调用了DllMain。

1.2.1 DLL_PROCESS_ATTACH

大家都知道,一个程序要调用Dll里的函数,首先要先把DLL文件映射到进程的地址空间。要把一个DLL文件映射到进程的地址空间,有两种方法:静态链接和动态链接的LoadLibrary或者LoadLibraryEx。

当一个DLL文件被映射到进程的地址空间时,系统调用该DLL的DllMain函数,传递的fdwReason参数为DLL_PROCESS_ATTACH。这种调用只会发生在第一次映射时。如果同一个进程后来为已经映射进来的DLL 再次调用LoadLibrary或者LoadLibraryEx,操作系统只会增加DLL的使用次数,它不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。不同进程用LoadLibrary同一个DLL时,每个进程的第一次映射都会用DLL_PROCESS_ATTACH调用 DLL的DllMain函数。

可参考DllMainTest的DLL_PROCESS_ATTACH_Test函数。

1.2.2 DLL_PROCESS_DETACH

当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的fdwReason值是DLL_PROCESS_DETACH。当DLL处理该值时,它应该执行进程相关的清理工作。

那么什么时候DLL被从进程的地址空间解除映射呢?两种情况:

◆FreeLibrary解除DLL映射(有几个LoadLibrary,就要有几个FreeLibrary)

       ◆进程结束而解除DLL映射,在进程结束前还没有解除DLL的映射,进程结束后会解除DLL映射。(如果进程的终结是因为调用了TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL 在进程结束前没有机会执行任何清理工作。)

注意:当用DLL_PROCESS_ATTACH调用DLL的DllMain函数时,如果返回FALSE,说明没有初始化成功,系统仍会用DLL_PROCESS_DETACH调用DLL的DllMain函数。因此,必须确保没有清理那些没有成功初始化的东西。

可参考DllMainTest的DLL_PROCESS_DETACH_Test函数。

1.2.3 DLL_THREAD_ATTACH

当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。

新创建的线程负责执行这次的DLL的DllMain函数,只有当所有的DLL都处理完这一通知后,系统才允许进程开始执行它的线程函数。

注意跟DLL_PROCESS_ATTACH的区别,我们在前面说过,第 n(n>=2)次以后地把DLL映像文件映射到进程的地址空间时,是不再用DLL_PROCESS_ATTACH调用DllMain的。而 DLL_THREAD_ATTACH不同,进程中的每次建立线程,都会用值DLL_THREAD_ATTACH调用DllMain函数,哪怕是线程中建立线程也一样。

1.2.4 DLL_THREAD_DETACH

如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。

注意:如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。

1.3  为DllMain换名

在早期的SDK版本中,DllMain是叫做DllEntryPoint。其实有一件鲜为人知的事:一个Dll的入口函数名是可以自己定义的。下面我将以VC++6.0为例来演示如何更改。首先要说明一点,虽然DllMain可以换成其他函数名,但函数的参数和返回值必须和DllMain一样。而且这个函数要为__stdcall类型(DllMain本身也是__stdcall类型)。

打开VC++菜单Project/Settings/Link tab/ Output in the Category box,如下图,在Entry-point symbol中输入要替换DllMain的函数名(当然这个函数名是你程序中已经实现的函数)。Entry-point symbol是干么的呢?可以以关键字“Entry-point symbol”搜索MSDN帮助文档查看,搜索时,打钩“仅搜索标题”会更快定位。

         按OK后,如果马上编译的话会出现如下错误:

LIBCMTD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main

Debug/Dll.dll : fatal error LNK1120: 1 unresolved externals

打开VC++菜单Project/Settings/C/C++选项卡,如下图,在Project Options:末尾的地方添加”/D”(图中蓝色高亮的地方),要注意位置,我试了,要把/D放到/GZ后面也会链接错误,我也不懂为什么,^_^。按OK,再次编译,成功。大家可以自己测试下到底有没有更改成功,什么,如果测试?打出调式信息啊。

1.4 DisableThreadLibraryCalls

看帮助就知道它是干么用的:

Windows Embedded CE does not support static-thread local storage; therefore, the only restriction for specifying a DLL to disable is that it is a valid module.

The DisableThreadLibraryCalls function lets a DLL disable the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notification calls.

This can be a useful optimization for multithreaded applications that have many DLLs, frequently create and delete threads, and whose DLLs do not need these thread-level notifications of attachment/detachment.

By disabling the notifications, the DLL initialization code is not paged-in because a thread is created or deleted, which reduces the size of the application's working code set.

Disabling the notification calls can be used for any DLL where there is no thread-level tracking required. If you need to track resources on a thread-by-thread basis, the notification should not be turned off.

To implement the optimization, modify a DLL's DLL_PROCESS_ATTACH code to call DisableThreadLibraryCalls.

Drivers that exist in the Device Manager Device.exe process space should call DisableThreadLibraryCalls if no thread-specific data is needed.

windows:加载dll时的DLLMain介绍 在实际开发中,通常情况下,系统自带的初始化和清理机制(如全局变量初始化和析构、自动内存管理等)已经足够。然而,有些特定场景下,需要开发者自己在DllMain中处理和。以下是一些可能的情况:线程本地存储(TLS)当需要在每个线程中维护独立的数据(如线程本地存储),必须手动进行线程初始化和清理。例如,多线程日志记录、线程特定的配置等。示例:每个线程都有独立的日志文件句柄或配置对象。资源管理当需要在DLL加载时分配全局资源(如文件句柄、网络连接)并在卸载时释放这些资源时,必须手动进行初始化和清理。示例。 阅读详情

相关推荐

C++动态链接库入口dllmain详解

通过使用dllmain函数,我们可以在DLL被加载和卸载时执行相应的初始化和释放资源操作。而在C++中,DLL的入口函数被称为dllmain。需要注意的是,dllmain函数是一个非常敏感的函数,它应该保持简洁并且不应该执行耗时的操作。在dllmain函数中,不建议创建新线程或进行复杂的初始化过程,因为这可能会导致不可预料的问题。除了在dllmain函数中执行初始化和释放资源的操作,我们还可以在DLL中定义其他函数供外部调用。dllmain函数是DLL中的特殊函数,它在DLL被加载和卸载时被调用。

2301_79331230的博客 1180

DLL文件_DLLMain函数详解

目录**CODE**1.DLLMain函数类型-APIENTRY CODE //核心的入口函数,动态链接库入口函数 BOOL APIENTRY DllMain( HMODULE hModule, //APIENTRY可以换成WINAPI或者_stdcall 是一种调用约定 DWORD ul_reason_for_call, LPVOID lpReserved )

weixin_46967682的博客 7368

告别米级误差:手把手教你用Nordic nRF52840实现厘米级蓝牙测距(Channel Sounding实战)

本文详细介绍了如何利用Nordic nRF52840开发板和蓝牙信道探测(Channel Sounding)技术实现厘米级高精度测距。通过硬件配置、软件优化和实战案例,帮助开发者快速掌握低功耗蓝牙测距技术,适用于工业自动化、智能仓储等场景。

weixin_42741930的博客 476

9.DLL的入口函数DllMain函数

1.dll的入口函数 类似程序的入口函数main或者WinMain一样,DLL也有一个入口函数,就是DllMain   2.DllMain函数原型 BOOL APIENTRY DllMain( HMODULE hModule, //指向自身的句柄 DWORD ul_reason_for_call, //调用原因 ...

renwu 8240

图像超分辨率在医学影像中的应用:如何用深度学习提升CT/MRI图像质量

本文探讨了深度学习驱动的图像超分辨率技术在医学影像(如CT/MRI)质量提升中的应用。文章分析了医学图像超分辨率在提升诊断信息含量、平衡保真度与临床相关性方面的独特挑战,并详细介绍了如何针对3D体数据特点定制模型架构、设计病理感知损失函数,以及解决高质量配对数据稀缺的策略。通过实战案例,阐述了从数据模拟、模型训练到临床评估的完整流程,旨在为医学影像的清晰化与诊断精准化提供有效解决方案。

weixin_29063681的博客 523

MySQL根据idb文件恢复数据

恢复前提 MySQL 5.* 和 8.* 的恢复方式大同小异,最基本的区别是8.* 中,不再有表结构frm文件,所以要恢复 8.* 的数据,就必须要有完整的建表语句。 而恢复 5.* 的数据,就需要idb文件和 frm文件,当然,如果有完整的建表语句的话,不用frm文件也行。 恢复步骤 需要注意的是,以下操作需要选定数据库后执行。 5.* 恢复表结构 确定表列数 首先创建一张 与需要恢复数据的表 的名字相同的新表,如果已知原表的字段数量的话,就按照原表字段数建表,字段名和类型都不用考虑,如果不知道数量的话,

weixin_45121446的博客 5447

4-DllMain详解

当线程C执行DIlMain函数中的代码时,线程B创建线程D,此时系统必须再次用DLL_THREAD_ATTACH来调用SomeDLL.dll的DllMain函数,但这次是让线程D来执行其中的代码。DllMain函数执行的时候,Windows会为它创建一个加载器锁,加载器锁可以被任意需要访问加载到进程中的DLL列表的函数获取到,这其中包括GetModuleHandle和GetModuleFileName之类的函数。DLL的入口函数一般被用作根据不同的通知信号,来执行相关的进程或线程的初始化和清理工作,

weixin_40332490的博客 1230

Chroma向量数据库实战:用Python快速搭建本地知识库(附中文诗词检索案例)

本文详细介绍了如何使用Chroma向量数据库和Python快速搭建本地知识库,并附有中文诗词检索的实战案例。通过解析核心概念、数据准备、向量化及智能检索实现,展示了Chroma在处理中文语义搜索时的轻量级与易用性,为开发者构建AI应用原型提供了实用指南。

weixin_29221753的博客 479

对DllMain的误解

     一直以来对DllMain的了解也就局限于,实验性的在DllMain里面写上: cout        我在DllMain里面这样写的代码:BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){

tangaowen的专栏 4368

Windows11 下 Detectron2 的安装与配置全攻略

本文提供了在Windows11系统下安装和配置Detectron2的完整教程。详细介绍了从环境准备、创建虚拟环境、安装PyTorch与CUDA,到修改源码、编译安装以及运行验证Demo的全过程,帮助开发者克服Windows平台上的常见问题,成功部署这一强大的计算机视觉库。

weixin_29081703的博客 246

如何在Vitis 2023.1上快速搭建LWIP Echo Server(附YT8521S PHY调试心得)

本文详细介绍了在Vitis 2023.1开发环境下,基于Xilinx MPSoC平台快速搭建LWIP Echo Server的完整实战流程。内容涵盖从Vivado硬件工程配置、Vitis软件工程创建,到关键代码剖析与定制化修改,并重点分享了调试非标准PHY芯片(如YT8521S)的宝贵心得与常见问题排查方法,旨在帮助开发者高效实现FPGA与上位机间的可靠网络通信验证。

weixin_29250403的博客 136

Windows动态库DllMain

DllMain DllMain是Windows动态库的入口函数。如同控制台或DOS程序需要main函数、WIN32程序需要WinMain函数一样,Windows在加载DLL的时候,需要一个入口函数。 注意事项 实际编写动态库时,DLL并没有提供DllMain函数,应用工程也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库中引入一个不做任何操作的缺省DllMain函数版本,并不意味着DLL可以放弃DllMain函数。 根据编写规范,Windows必须

beibeix2015的博客 1005

ArcGIS基于DEM提取微流域单元(附练习数据下载)

流域作为一个相对独立的地理单元,与行政区的划分有着本质上的区别。流域的划分更注重自然因素,流域作为一个综合的自然整体,在其内部形成了一个天然的物质与能量流动的场所,并通过水流的作用,与周围的区域进行物质和能量的交换。流域的精确划分作为一个研究的基础工作,那么接下来给大家说一下利用DEM提取小流域的案例教程——以贵州省遵义市正安县为例。 1 数据获取 地理空间数据云(http://www.gscloud.cn/),数据分辨率为30m。也可直接点击这篇直接下载→全国30m90mDEM下载。 若想要获得更高精度.

qq_43173805的博客 4834

DllMain中不当操作导致死锁问题的分析--进程对DllMain函数的调用规律的研究和分析

不知道大家是否思考过一个过程:系统试图运行我们写的程序,它是怎么知道程序起始位置的?很多同学想到,我们在编写程序时有个函数,类似Main这样的名字。是的!这就是系统给我们提供的控制程序最开始的地方(注意这儿是提供给我们的,而实际有比这个还要靠前的main)。于是看到DllMain就可以想到它是干嘛的了:Dll的入口点函数。那何时调用这个函数的呢?以及各种调用场景都传给了它什么参数呢...

方亮的专栏 6673

数字逻辑Fundamentals of Digital Logic with Verilog Design | 3rd Edition Solutins Chapter 3(step by step)

第三章3-1~3-27全部习题解析和代码模块

weixin_62651190的博客 1946

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

DLL专题之DllMain函数

DllMain函数,并没有什么好讲的.不就是加载和卸载DLL的时候用嘛!实际上,也不是这样.在一些高级应用中是很有用处的.今天,我们只是简单的测试测试.没有什么技术含量的.呵呵.那我们就看看吧:首先,老步骤,建立一个Win32 DynamicLink(dll)选择一个简单的工程.,代码如下:头文件:#ifndef _DLLMAIN_DLL_H_#define _DLLMAIN_DLL_

章志强 8574

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

关于dllMain死锁的问题

前几天遇到了一个死锁问题,查了很久没查出来,最后发现是在dllMain中结束线程导致死锁。 起因:是修改了某个模块,在init函数里启动线程,在uninit函数里结束线程,开始并不知道init和uninit是从dllMain调过来的,也不知道dllmain中结束线程会导致死锁。 具体原因:每次进入dllMain时都会持有一个loader-lock,而结束线程也会进入dllMain,结果就死锁了

mxc的专栏 635

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

DllMain

转自:https://docs.microsoft.com/zh-cn/windows/win32/dlls/dllmain

yjianlu的专栏 189

在DLL 的DllMain函数中创建线程

最近在写一个代码的时候想在DLL的DllMain

bobopeng 6866
上一篇: S3C2410中断分析
下一篇: 一个ActiveSync无法连接的解决方法
renpine
博客等级 码龄20年 14粉丝 11原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值