windows核心编程 19

来源:互联网 发布:linux管理面板 编辑:程序博客网 时间:2024/06/06 01:10

DLL能够包含诸如对话框模板、字符串、图标以及位图之类的资源。多个应用程序可以使用DLL来共享这些资源。

 

在所有的源文件编译完成之后,链接器会像链接应用程序的可执行文件那样,对它们进行链接,但在创建DLL的时候,我们必须给链接器指定/DLL开关。这个开关会使链接器在生成的DLL文件映像中保存一些与可执行文件略微不同的信息,这样操作系统的加载程序就能够将该文件映像识别为DLL,而不会将它识别为应用程序。

当线程调用DLL中的一个函数的时候,该函数会在线程栈中取得传给它的参数,并使用线程栈来存放它需要的局部变量。此外,该DLL中的函数创建的任何对象都为调用线程或调用进程所拥有—DLL绝对不会拥有任何对象。

当一个模块提供一个内存分配函数的时候,它必须同时提供另一个用来释放内存的函数。

可执行模块包含一个导入段(importsection),其中列出了所有它需要的DLL模块的名称。此外,对列出的每个DLL,该段还记录了可执行文件的二进制代码从中引用的函数和变量的符号名。

一个DLL可以导出变量、函数或C++类来供其他模块使用。在实际开发中,我们应该避免从DLL中导出变量,因为这等于是去掉了代码中的一个抽象层,从而使得DLL的代码更加难以维护。此外,只有当导出C++类的模块使用的编译器与导入C++类的模块使用的编译器由同一家厂商提供时,我们才可以导出C++类。因此,除非知道可执行模块的开发人员与DLL模块的开发人员使用的是相同的工具包,否则我们应该避免从DLL中导出C++类。

 

MyLib.h

#ifndef MYLIBAPI

#define MYLIBAPIextern “C” __declspec(dllimport)

#endif

MYLIBAPI intAdd(int a, int b);

 

MLib.cpp

#define MYLIBAPIextern “C” __declspec(dllexport)

#include“Mylib.h”

int add(int a,int b)

{

         return a + b;

}

 

         如果编译器看到一个变量、函数或C++类是用__declspec(dllexport)修饰的,那么它就知道应该在生成的DLL模块中导出该变量、函数或C++类。

 

         当使用__stdcall来导出C函数的时候,Microsoft的编译器会对函数名进行改编,具体的方法是给函数名添加下划线前缀和一个特殊的后缀,该后缀由一个@符号后跟作为参数传给函数的字节数组成。为了导出原名,需要建立.def文件。

         如果编译器看到一个变量、函数、或C++类是用__declspec(dllimport)来修饰的,那么它会知道应该是从某个DLL模块中导入该符号。编译器不知道,也不需要知道具体的DLL模块是哪一个。编译器只想确认我们以正确的方式来访问这些导入符号。

         接下来,为了创建可执行模块,链接器必须将所有的.obj模块合并到一起。由于链接器必须确定代码中引用的导入符号来自哪个DLL,因此我们必须将DLL的.lib文件传给链接器。正如我们前面已经提到过,.lib文件只不过是列出了DLL模块导出的符号。链接器只想知道被引用的符号确实存在,以及该符号来自哪个DLL模块。如果链接器能够解决(resolve)对所有外部符号的引用,那么它将生成可执行模块。

 

         启动一个可执行模块的时候,操作系统的加载程序会先为进程创建虚拟地址空间,接着把可执行模块映射到进程的地址空间中。之后加载程序会检查可执行模块的导入段,试图对所需的DLL进行定位并将它们映射到进程的地址空间中。

 

         由于加载程序会对载入的DLL模块进行记录,因此即使多个模块用到了同一个模块,该模块也只会被载入和映射一次。

 

         当加载程序将所有DLL模块都载入并映射到进程的地址空间中后,它开始修复所有对导入符号的引用。为了完成这一工作,它会再次查看每个模块的导入段。对导入段中列出的每个符号,加载程序会检查对应DLL的导出段,看该符号是否存在。如果该符号不存在(这种情况实属罕见),那么加载程序会出现错误提示框。如果该符号存在,那么加载程序会取得该符号的RVA并给它加上DLL模块被载入到的虚拟地址(从而得到符号在进程的地址空间中的位置)。接着加载程序会将这个虚拟地址保存到可执行模块的导入段中。现在,当代码引用到一个导入符号的时候,会查看调用模块的导入段并得到被导入符号的地址,这样就能够成功地访问被导入的变量、函数或C++类成员函数了。

 

 

0 0