动态链接库有很多优点:
•扩展了应用程序的特性
•可以用许多种编程语言来编写
•简化了软件项目的管理
•有助于节省内存
•有助于资源的共享
•有助于应用程序的本地化
•有助于解决平台差异
•可以用于一些特殊的目的

一.动态链接库的创建过程

创造DLL:1) 建立带有输出原型/结构/符号的头文件。2) 建立实现输出函数/变量的C/C++源文件。3) 编译器为每个C/C++源文件生成.obj模块。4) 链接程序将生成DLL的.obj模块链接起来。5) 如果至少输出一个函数/变量,那么链接程序也生成lib 文件。
创造EXE:
6) 建立带有输入原型/结构/符号的头文件。7) 建立引用输入函数/变量的C/C++源文件。8) 编译器为每个C/C++源文件生成.obj源文件。9) 链接程序将各个.obj模块链接起来,产生一个.exe文件
   (它包含了所需要DLL模块的名字和输入符号的列表)。
运行应用程序:
10) 加载程序为.exe 创建地址空间。11) 加载程序将需要的DLL加载到地址空间中进程的主线程开始执行;
    应用程序启动运行。

二.创建\使用动态链接库
首先必须创建一个包含需要导出的符号的头文件,以便其他程序链接到该dll上:

// dllexample.h
#ifdef DLLEXAMPLE_EXPORTS // 在编译命令中已定义,所以实际用的是 __declspec(dllexport)
#defineDLLEXAMPLE_API __declspec(dllexport)#else#defineDLLEXAMPLE_API __declspec(dllimport)#endif
DLLEXAMPLE_API
intfnDllexample(void);

当其他应用包含该头文件,意图使用该dll的导出符号时,因为没有定义DLLEXAMPLE_EXPORTS,所以使用的是__declspec(dllimport),这样编译器编译时便知道这是从外部引入的函数。在链接时,链接程序将生成导入表(ImportAddressTable),该表罗列了所有调用到的函数,以及一个空白的对应地址。在程序执行时,加载器将动态的填入每个函数符号在本进程中的地址,使得程序能正确的调用到dll中的函数上。

这种通过dll提供的.h和.lib文件进行链接dll的使用方式,称为隐式链接。用vc开发程序时,几乎所有的系统API调用都用了隐式链接。

三.显式链接
在exe创建时不引用.lib文件中的符号,当然也不必包含.h头文件,而是由程序调用LoadLibrary(Ex)以及GetProcAddress函数来获取每个需要使用的函数地址,从而进行dll中的函数调用,这种dll使用方法称为显式链接。显式链接时不生成对应dll的IAT.

当决定不再使用该dll时,通过调用FreeLibrary来卸载。需要注意的是,同一个进程中共计调用LoadLibrary的次数要和调用FreeLibrary的次数相等,因为系统维护了一个使用计数,当计数为0时,才会真正的卸载该dll.

如果想确认一个dll是否已经被映射到进程空间中,尽量使用GetModuleHandle,最好不要冒然使用LoadLibrary(Ex).

GetProcAddress可以传递函数名或者序号(通过MAKEINTRESOURCE(2)来"制作"序号).

四.DllMain(Dll入口)
其实,DllMain函数并不是最初的入口,它被_DllMainCRTStartup函数调用。
当系统调用_DllMainCRTStartup并传递DLL_PROCESS_ATTACH时,此函数初始化Dll中的所有全局变量以及静态成员变量等等,然后才调用DllMain并传递DLL_PROCESS_ATTACH;当系统传递DLL_PROCESS_DETACH时,此函数首先调用DllMain并传递DLL_PROCESS_DETACH,当DllMain返回后才调用全局或静态变量的析构函数。
如果不想在进程创建或销毁时收到DLL_THREAD_ATTACH或者DLL_THREAD_DETACH消息,那么可以在DLL_PROCESS_ATTACH时调用DisableThreadLibraryCalls,这将提高一些效率。

五.延迟加载Dll
说实话以前没有注意过这么一个好用的特性。看过本节后我知道了它。延迟加载用于隐式链接Dll的程序中。
要使一个dll延迟加载,就要在.exe上做手脚。需要修改工程属性,添加如下命令,则在链接时在输入节中将不包含该Dll的任何信息,从而导致.exe加载时不会加载该Dll.

/Lib:DelayImp.lib/DelayLoad:MyDll.dll

这样,基本上就已经完成了对一个Dll延迟加载的处理。关于具体原理,书中是这样说的:

The/Libswitchtells the linker to embed a special function, _ _delayLoadHelper, into your executable. The secondswitchtells the linker the following things:
•Remove MyDll.dll from the executable module
's import section so that the operating system loader does not implicitly load the DLL when the process initializes.•Embed anewDelay Import section (called .didata)inthe executable indicating which functions are being imported from MyDll.dll.
•Resolve calls to the delay
-loaded functions by having calls jump to the _ _delayLoadHelper function.

如果短期内不想使用延迟加载的dll,那么可以暂时卸载它,需要的操作是添加一个链接开关:
/Delay:unload
然后在代码中,需要想要卸载Dll的地方调用  _ _FUnloadDelayLoadedDLL ,传递的名字必须与 /DelayLoad 开关所传递的名字完全相同(包括大小写)。不要使用FreeLibrary代替 _ _FUnloadDelayLoadedDLL 。如果不添加/Delay:unload开关而调用 _ _FUnloadDelayLoadedDLL ,那么这个函数会返回FALSE而不卸载任何dll.

六.函数转发器
函数转发器其实就是在Dll的导出函数里直接调用另一个Dll的函数。可以给自己创建的Dll的添加一些转发器,借花献佛。

//Function forwarders to functions in DllWork#pragmacomment(linker, "/export:SomeFunc=DllWork.SomeOtherFunc")

七.改变dll的基址
最好给自己创建的可能在同一工程中使用的不同Dll分别制定不同的Base Address,这样可以避免多个Dll同时要求映射到同一地址。虽然不会导致程序崩溃,但是系统要额外的重新定位剩余Dll中的地址。
方法是使用/base:"0x--------"链接命令。

八.绑定模块
待定

转载于:https://www.cnblogs.com/yoran/archive/2008/03/03/1088411.html

windows核心编程学习笔记(六)动态链接库相关推荐

  1. 转 windows核心编程 学习笔记 目录

    windows核心编程--SEH(结构异常处理) SEH 的工作原理.         Windows 程序设计中最重要的理念就是消息传递,事件驱动.当GUI应用程序触发一个消息时,系统将把该消息放入 ...

  2. Windows核心编程学习笔记

    字符串处理 strcpy和wcscpy不安全,是因为无法判断缓冲区最大长度的参数,不知道是否会破坏内存 一个进程-> 一个内核对象+一个地址空间 每个对象只是一个内存块 文件地址包括字节偏移量. ...

  3. windows核心编程学习笔记(八)结构化异常处理(Structured Exception Handling)

    首先要要知道,结构化异常处理(SEH)和C++提供的异常处理不相同. 一.Termination HandlersTermination Handlers使用很简单.在想使用SEH处理的地方使用 __ ...

  4. 窗口消息——Windows核心编程学习手札之二十六

    窗口消息 --Windows核心编程学习手札之二十六 Windows允许一个进程至多建立10000个不同类型的用户对象(user object):图符.光标.窗口类.菜单.加速键表等,当一个线程调用一 ...

  5. 线程的堆栈——Windows核心编程学习手札之十六

    线程的堆栈 --Windows核心编程学习手札之十六 系统会在进程的地址空间内保存一些区域,同时也会在进程地址空间内为线程的堆栈保留区域.线程都有自己的堆栈,创建时,系统就保留一个堆栈空间区域,并将相 ...

  6. [笔记]Windows核心编程《十六》线程栈

    系列文章目录 [笔记]Windows核心编程<一>错误处理.字符编码 [笔记]Windows核心编程<二>内核对象 [笔记]Windows核心编程<三>进程 [笔记 ...

  7. 内存映射文件——Windows核心编程学习手札之十七

    内存映射文件 --Windows核心编程学习手札之十七 与虚拟内存一样,内存映射文件保留地址空间,并将物理存储器提交给该区域,差别在于所提交的物理存储器是磁盘上有文件存在的空间,而非系统的页文件,一旦 ...

  8. 线程基础知识——Windows核心编程学习手札系列之六

    线程基础知识 --Windows核心编程学习手札系列之六 线程与进程一样由两部分构成:一是线程的内核对象,操作系统用它来对线程实施管理,也是系统用来存放线程统计信息的地方:二是线程堆栈,用于维护线程在 ...

  9. 未处理异常和C++异常——Windows核心编程学习手札之二十五

    未处理异常和C++异常 --Windows核心编程学习手札之二十五 当一个异常过滤器返回EXCEPTION_CONTINUE_SEARCH标识符时是告诉系统继续上溯调用树,寻找另外的异常过滤器,但当每 ...

最新文章

  1. R语言使用ggplot2包使用geom_dotplot函数绘制分组点图(添加均值、标准偏差)实战(dot plot)
  2. 从Grid R-CNN到Grid R-CNN Plus:基于网格的目标检测演化
  3. Node.js 路由的简单使用
  4. 《BI那点儿事》运用标准计分和离差——分析三国超一流统帅综合实力排名 绝对客观,数据说话...
  5. org.apache.struts2.json.JSONException: java.lang.reflect.InvocationTargetException异常解决
  6. 计算机视觉三大会议——ICCV、ECCV和CVPR
  7. 干货|设计师都收藏的9个实用灵感网站!
  8. Android studio 设置默认打开项目,默认打开项目方式
  9. java 枚举 映射_java – 如何将值映射到枚举?
  10. 最新O泡易支付系统源码-源码全解密,无后门,本地资源化
  11. 关于关系型数据库锁机制的理解
  12. ESD介绍及TVS的原理和应用-USB等
  13. [netfilter]-ip_rcv包转发流程
  14. 重磅开源:阿里妈妈技术质量开源了线上测试MagicOTP和性能测试平台ACP
  15. 数字+字母+特殊字符 的正则表达式
  16. 基于浙大MO平台的开发机器学习算法
  17. HTML5 <a> 标签
  18. 开贝修图最新版 免狗全功能版
  19. 今夏成为小葫芦娃的最后机会!
  20. 什么是因果?什么是相关?

热门文章

  1. wand java源码_ImageMagick使用for java(im4java)
  2. python作者龟叔_龟叔和他的Python
  3. 记录一下海上风力机机械装置
  4. 实现MFC中Radio Button组绑定同一变量控制
  5. php7 windows2008,【笔记】Windows Server2008 R2 安装 PHP7 缺少 API-ms-win-crt-runtime-l1-1-0.dll 解决方案...
  6. (原創) 將map輸出到cout,是否有更方便的方法? (C/C++) (STL)
  7. bind函数作用、应用场景以及模拟实现
  8. leetcode897
  9. 部署Exchange Server 2007 SCC
  10. oracle 12c 13姨