DllMain详解

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的映射的情况。(如果进程的终结是因为调用了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 
看帮助就知道它是干么用的: 
The DisableThreadLibraryCalls function disables the DLL_THREAD_ATTACH and DLL_THREAD_DETACH notifications for the dynamic-link library (DLL) specified byhLibModule. This can reduce the size of the working code set for some applications.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/434504.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 视频学习

Linux 系统管理员要求对系统进行管理,备份等操作,linux程序员需要掌握c,c,java,php,jsp等 Linux平台上的开发,包括vi,gcc,gdb,make,jdk,tomcat,mysql… 书籍介绍:鸟哥LINUX私房菜,LINUX编程从入门到精通,li…

linux安装tensorflow教程,真正从零开始,TensorFlow详细安装入门图文教程!

在正式开始之前我想说:一定要注意窗口给出的提示(英文)。在实际操作中可能会碰到各种各样的问题,但常见的问题其实都可以根据它的报错信息找到原因,只要上网搜一搜相应的信息就能解决,甚至它自己就会给出解决的建议。如果你发现你…

引路蜂地图API:Gis.Navigation包定义

本包提供了路口到路口实时导航API,从地图服务器返回的路径信息含有文字和路径的地理坐标信息,类NavigationEngine根据路径和当前坐标实现实时导航。它内部含用三个工作线程: Location Monitor 实时监视当前位置坐标是否偏离路径,如…

ubuntu下安装opensips

1. 下载opensips1.8版本,并解压到 "/usr/local/src" 目录下 ;2. 安装必要的软件包,apt-get install flex bison libncurses-dev3. 进入opensips源码目录,make menuconfig出现opensips的配置界面后1) 选择"Configur…

linux 修改Db2主机名,修改DB2服务器的主机名

环境:产品:DB2 UDB平台:AIX,Solaris,HP-UX,Linux,Windows版本:V8 V9.1V9.5为了修改服务器的主机名,我们可以在DB2数据库服务器上执行以下步骤来实现:1) 停止DB2管理服务器…

用OpenMP加速你的程序[转]

最近在看多核编程。简单来说,由于现在电脑CPU一般都有两个核,4核与8核的CPU也逐渐走入了寻常百姓家,传统的单线程编程方式难以发挥多核 CPU的强大功能,于是多核编程应运而生。按照我的理解,多核编程可以认为是对多线程…

错误./hello: error while loading shared libraries: libQtGui.so.4: cannot open shared object file:

之前一直想在ARM 上跑qt,但都出现错误: ./hello: error while loading shared libraries: libQtGui.so.4: cannot open shared object file: No such file or directory 这主要是ARM 上的运行环境设置不当: 我用的是飞凌的6410 环境变量设…

linux 指令引用变量,Linux之变量引用与命令替换

在bash脚本编写中,我们时常需要引用变量与替换命令,为规范操作,现对其做简单的总结说明。引用引用就是指将字符串用引用符号括起来,以防止特殊字符被shell脚本解释为其他意义。引用时屏蔽特殊字符的特殊意义,而将其解释…

有些垃圾网站转载都不会

有时会看到我的文章被转载,只要保留作者信息和原文链接,并且忠实于原文都是很欢迎的。这里的忠实原文应该是最基本的了吧,转载嘛,最简单的也就是拷贝粘贴吧,可发现有些垃圾网站,连拷贝粘贴都做不好&#xf…

移植tslib到开发板及部分问题解决

qt的tslib的具体移植步骤和过程就不多讲了,我说说我按照手册移植好tslib后在开发板运行提示的错误以及我的解决方法,当然每个人的提示可能一样,解决方法就不一样,我也是个初学者,所以方法仅供大家参考!问题…

Content Provider 基础 之URI

Keywords: content provider, URIContent Provider这个东西在Android平台上是最常用的共享数据的方法(似乎应用程序之间共享数据也只有这种方法吧,待求证)。虽然常用,但是这个东 西要理解透彻还是要先掌握一些基础的。URI就是Cont…

linux shell 原理,linux下shell的工作原理

linux下shell的工作原理2009-12-8 10:19:53 出处:https://www.yqdown.comshell是用户和Linux操作系统之间的接口。Linux中有多种shell,其中缺省运用的是Bash。本章讲述了shell的工作原理,shell的种类,shell的一般操作及Bash的特…

解决SerMyAdmin无法登陆的问题

1. 首先确认默认的用户名和密码,因为每个版本的SerMyAdmin的默认用户名密码可能不同,根据 《Building Telephony Systems with OpenSIPS 1.6》这本书上所说的SerMyAdmin的用户名和密码是 adminsetup和secret。但是从我的SerMyAdmin安装包里的MySql数据…

oracle.cmd

--更改列顺序 SELECT * FROM ALL_OBJECTS WHERE OWNER TDDJ AND OBJECT_NAMELSZD_JZDZB AND OBJECT_TYPETABLE--54529 SELECT OBJ#,COL#,NAME FROM SYS.COL$ WHERE OBJ# 57689; UPDATE SYS.COL$ SET COL# 9 WHERE OBJ# 57689 AND NAME XMBM; UPDATE SYS.COL$ SET COL# 7 WHE…

Linux部署动态网页,linux构建动态WEB服务器安装篇

linux构建动态WEB服务器安装篇发布时间:2008-09-18 08:50:01 作者:佚名 我要评论基本配置安装web服务器:httpd-2.X.X先优化吧根据CPU设置变量#export CFLAGS”-O2 -marchpentium4 -pipe” && CXXFLAGS$CFLAGS“-march”选项表示为特定的cpu…

sip事务与对话

一个事务通常由一个请求开始,由一个响应码(a response code)结束。VIA头域中的branch参数用来标识一个事务。 对话可以是开始于一个INVITE事务,结束于一个BYE事务。一个对话由FROM,TO和CALL-ID头域的结合所…

[转]Win7 系统安装VS2008没反应 点击安装一闪就没有反应 .

原文地址:http://blog.csdn.net/mingjie_520/article/details/6757960 Win7 系统上用虚拟光驱安装 VS2008 没反应,安装不启解决方案VS2008 ISO境像文件,解开来安装的话,也没有问题,不过真的很慢,解出又占空…

apt-get的更新源

1、先备份 sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup (备份下当前的源列表,有备无患嘛.) 2、修改更新源 sudo gedit /etc/apt/sources.list (打开源列表文件) 3、修改 deb http://mirrors.sohu.com…

电脑用linux命令大全,电脑操作时常用的一些Linux命令

电脑操作时常用的一些Linux命令1、修改密码:passwd用户名2、下载jdk-6u25-linux-i586.bin3、运行(cd进入某一目录后,/usr/jdk-6u25-linux-i586.bin解压缩操作)sh jdk-6u25-linux-i586.bin4、到opadmin home目录下改环境变量vi .bash_profile编辑用户主目…

在WIN7下硬盘安装XP双系统

在WIN7下硬盘安装XP双系统 对安装过程有疑问的朋友们请在雨林木风论坛 请教其他高手吧,他们很热心的!对于有些人提的许多很白痴的问题的确爱莫能助了。。 很多朋友因为WIN7的美观界面和方便的操作而放弃了xp,但是用过一段时间的WIN7后会发现…