什么是DLL?

解决方案 »

  1.   

    这个问题高深!DLL是一种程序文件,叫动态链接库。提供一些接口函数给可执行文件使用。例如:我们常用的API函数ShellExec()
      

  2.   

    转自DELPHI5开发人员指南本章讨论了Wi n 3 2动态链接库,也就是D L L。D L L是用来编写Wi n d o w s应用程序的关键组成部分。
    本章讨论了使用和创建D L L的几个方面,它给出了D L L怎样工作的概述并讨论了怎样创建和使用D L L,
    你将学会怎样调入D L L和链接由它们引出的过程和函数的不同方法。本章还包括回调函数的使用并举
    例说明在不同调用进程中如何实现共享数据。
    9.1 究竟什么是DLL
    动态链接库是程序模块,它包括代码、数据或资源,能够被其他的Wi n d o w s应用程序共享。D L L
    的主要特点之一是应用程序可以在运行时调入代码执行,而不是在编译时链接代码,因此,多个应用
    程序可以共享同一个D L L的代码。事实上,文件K e r n e l 3 2 . d l l、U s e r 3 2 . d l l、G D I 3 2 . d l l就是核心Wi n 3 2系
    统的动态链接库。K e r n e l . d l l负责内存、进程和线程的管理。U S E R 3 2 . D L L包含了一些程序,是创建窗
    口和处理Wi n 3 2消息的用户接口。G D I 3 2 . D L L负责处理图形。你还会听说其他的系统D L L,譬如
    A d v A P I 3 2 . d l l和C o m D l g 3 2 . d l l,它们分别处理对象安全性/注册操作和通用对话框。
    使用动态链接库的另一个特点是有利于应用程序的模块化。这样就简化了应用程序的修改,因为
    一般只需要修改D L L,而不是整个应用程序。Wi n d o w s环境自身就是模块化类型的典型实例。每当安
    装一个新设备,就安装一个设备驱动程序(即D L L ),使设备能够与Wi n d o w s相互通信。
    在磁盘上,一个D L L基本上类似于一个Wi n d o w s可执行文件( * . E X E )。一个主要的区别是, D L L不是
    一个独立的可执行文件,尽管它可能包含了可执行代码。大部分D L L文件的扩展名是. d l l,也有的可能
    是. d r v (设备驱动程序)、. s y s (系统文件)、. f o n (字体文件),这些不包含可执行代码。
    注意Delphi引入了一种叫做程序包的特殊用途的DLL,它应用于Delphi和C++编程环境。我们
    将在第21章深入探究程序包。
    D L L通过动态链接技术(dynamic linking)与其他应用程序共享代码,这将在本章后面部分讨论。总
    之,当一个应用程序使用了一个D L L,Wi n 3 2系统会确保内存中只有一个该D L L的拷贝,这是通过内
    存映射文件来实现的。D L L首先被调入Wi n 3 2的全局堆,然后映射到调用这个D L L进程的地址空间。
    在Wi n 3 2系统中,每个进程都被分配有自己的3 2位线性地址空间。当一个D L L被多个进程调用时,每
    个进程都会获得该D L L的一份映像。因此,在1 6位Wi n d o w s中,程序代码、数据、资源不被进程共享,
    而在Wi n 3 2中,D L L是可以被看作是属于调用该D L L进程自己的代码。为得到关于Wi n 3 2概念的更多信
    息,请参阅第3章“Win32 API”。
    但这并不意味着,如果多进程调用一个D L L,物理内存就分配有该D L L的每个实例。通过从系统
    的全局堆到调用该D L L的每一进程的地址空间的映射, D L L映像置于每个进程的地址空间。至少在理
    想情况下应这样。
    设置DLL的首选基地址
    如果D L L被调入进程的地址空间时设置了基地址,这样D L L数据就可以被共享。如果D L L
    的基地址与已经分配的D L L地址重叠的话,Wi n 3 2重新分配基地址。这样,每一个重新分配的
    DLL实例都有自己的物理上的内存空间和交换文件空间。
    这是很关键的,通过使用$ I M A G E B A S E指示符,给每个D L L都设置一个基地址,这样不
    会引起冲突或不会出现地址重叠。
    如果有多个应用程序都调用同一个D L L,设置一个唯一的基地址,这样无论是在进程的低
    端地址或者是在一般的D L L (如V C L包)的高端地址,都不会引起冲突。一般可执行文件( E X E和
    D L L )缺省的基地址为$ 4 0 0 0 0 0,这就意味着,除非修改D L L的基地址,否则就会与主程序的基
    地址引起冲突,因此进程间也就不能共享DLL的数据。
    在调用时,D L L不需要重新分配或安装,因为它保存在本地磁盘上,D L L的内存页面被直
    接映射到磁盘上的D L L文件。D L L代码不需占用系统页面文件(也叫交换文件)的空间。这就是
    为什么系统提交页的总数和大小可能比系统交换文件加内存要大。
    你可以参阅Delphi 5的在线帮助中的“Image Base Address”,那里有使用$ I M A G E B A S E指
    示符的详细介绍。
    有关D L L的一些术语如下:
    . 应用程序,一个扩展名为. e x e的Wi n d o w s程序。
    . 可执行文件,一个包含可执行代码的文件,它包括. d l l文件和. e x e文件。
    . 实例,当提到应用程序和D L L时,在内存中出现的可执行文件就是实例。Wi n 3 2系统通过实例句
    柄的方式来引用实例。例如,如果一个应用程序运行两次,就会有应用程序的两个实例,同时
    就有两个实例句柄。当一个D L L被调入时,实例及其相应的实例句柄同时产生。应该注意的是,
    这里所提的实例与类的实例不能混淆。
    . 模块,在3 2位Wi n d o w s系统中,模块和实例可以说是同义的。而在1 6位的Wi n d o w s系统中,是建
    立一个模块数据库来管理模块的,一个模块对应一个模块句柄。在Wi n 3 2中,应用程序的每一个
    实例都拥有自己的地址空间;所以,没有必要为模块单独指定标识符。不过,微软仍然保留了
    它自己的术语。注意一点,模块和实例是同一个概念。
    . 任务,Wi n d o w s是一个多任务(或任务切换)环境,所以它必须能够为运行的多个实例合理分配系
    统资源和时间。于是,Wi n d o w s建立一个任务数据库,这个数据库包括任务的实例句柄和其他必
    要信息,以此实现任务切换功能。任务是Wi n d o w s用来管理和分配资源与时间段的重要元素。
    9.2 静态链接与动态链接
    静态链接是指D e l p h i编译器把要调用的函数和过程编译成可执行代码。函数的代码可存留在应用
    程序的. d p r文件或一单元中。当链接用户的应用程序时,这些函数与过程便成为最终的可执行文件的
    第9章动态链接库
    一部分。也就是说,函数和过程都在程序的. e x e文件中。
    程序运行时,函数和过程随程序一起调入内存,它们的位置与程序的位置是相关的。当主程序需
    要调用函数或过程时,流程将跳转到函数或过程所在的位置,执行完函数或过程的代码,将返回主程
    序调用位置。而函数或过程的相对位置,在链接时就已经确定了。
    以上是对D e l p h i编译器进行静态链接这一复杂过程的简单描述。不过,本书并不是要你了解编译
    器在背后的具体操作。
    注意D e l p h i实现一个智能链接器,可以自动地把项目中没有引用的函数、过程和有类型的常
    量去掉,那么,最后的可执行文件就不会有冗余的代码。
    假设有两个应用程序,都要调用一个单元的同一个函数,当然,这两个应用程序都要在其u s e s子
    句中包含该单元。如果这两个程序要同时运行,那么内存中就存在两份该函数,如果还有第三个这样
    的应用程序,内存中就会有第三份该函数的实例,这样,就会三次占据内存。这个小例子就表明了动
    态链接的优越性之一。函数通过动态链接,被放到一个D L L中。那么如果一个应用程序把该函数调入
    内存,其他应用程序就可以通过映射D L L的映像到自己进程内存空间来共享代码。理论上讲,最终结
    果是内存中只存在该D L L的一份实例。
    对于动态链接,在程序运行时,通过引用一个外部函数(该函数包含在D L L中)而将该函数链接到
    可执行文件中。其中的引用可以在应用程序中声明,但是通常情况下是放在一个专门的引入( i m p o r t )单
    元里,在这个单元里可以声明引入的函数、过程以及D L L所需的多种类型的定义。
    例如,假设有一个叫M a x L i b . d l l的动态链接库,其中包含一个函数:
    这个函数返回两个整数中较大的一个数,一个典型的引入单元如下:
    你也许注意到了,这看上去类似于一般的单元,但这个单元没有定义M a x ( )函数。关键字e x t e r n a l
    后面的字符串就是该D L L的名称。要使用这个单元,应用程序只需把M a x U n i t加到它的u s e s子句中即可。
    当这个程序运行时,该D L L就会自动地被调入内存,并且任何需要调用M a x ( )的程序都被链接到这个
    D L L中的M a x ( )函数。
    调用D L L有两种方式,这是其中一种,叫隐式调用,就是让Wi n d o w s在应用程序调入时自动地调
    入所要调用的D L L;另一种是显式调用,这个将在本章节的后面讨论。
      

  3.   

    9.3 为什么要使用DLL
    使用D L L有若干理由,其中有一些前面已经提到过了。大体说来,使用动态链接库可以共享代码、
    系统资源,可以隐藏实现的代码或底层的系统例程、设计自定义控件。下面将分别讨论这几个方面的
    内容。
    9.3.1 共享代码、资源和数据
    在本章节前面已经提到,共享代码是创建动态链接库的主要目的所在。但与单元的代码共享不同,
    D L L的代码可以被任何Wi n d o w s应用程序共享,而单元代码的共享局限于D e l p h i应用程序。
    另外,D L L提供了共享资源的途径,诸如位图、字体、图标等等这些都可以放到一个资源文件中,
    并直接链接到应用程序。如果把这些资源放到D L L中,那么就可以让许多应用程序使用,而不必在内存里重复装入这些资源。
    在1 6位的Wi n d o w s中,D L L有自己的数据段,于是,所有要调用同一个D L L的应用程序能够访问
    同一个全局变量和静态变量。但在Wi n 3 2系统中,这就不同了。因为D L L的映像被映射到每个进程的
    地址空间,该D L L的所有数据属于映射到的进程。值得一说的是,尽管进程间不能共享D L L的数据,
    但是同一个进程的所有线程可以共享,因为线程是相互独立的,所以在访问某一D L L的全局变量时,
    务必小心,防止引起冲突。
    但这并不意味着没有办法实现在进程间共享一个D L L的数据。一个技术可以通过内存映射文件的
    方法在内存中创建一个共享的区域。一切需调用D L L的应用程序都可以读这些存储在内存中的共享区
    域的数据。这个技术将在本章的后面详细介绍。
    9.3.2 隐藏实现的细节
    有些时候,你可能想隐藏例程实现的细节, D L L就可以实现这一点。不管为何要隐藏你的代码,
    D L L可以使函数被应用程序访问,而其中的代码细节不被显现,你所要做的只是提供别人能访问D L L的
    接口。你也许认为D e l p h i的编译单元( D C U )也可以隐藏细节,但是D C U只适用于D e l p h i应用程序,而且还
    受版本的局限。而D L L与语言无关,所以,创建的D L L可以被C + +、V B或其他任何支持D L L的语言调用。
    Wi n d o w s单元是Win32 DLL的接口单元。Delphi 5提供了Win32 API的源文件,其一是Wi n d o w s单
    元的源文件w i n d o w s . p a s,在该文件的i n t e r f a c e部分有如下定义:
    为链接到相应的D L L,在其i m p l e m e n t a t i o n部分,有如下的例子:
    这行代码的意思表明,C l i e n t To S r e e n ( )在动态链接库U s e r 3 2 . d l l中,它的名称叫C l i e n t To S r e e n .
    9.3.3 自定义控件
    自定义控件通常放在D L L中。这些控件不同于D e l p h i的自定义组件。自定义控件是在Wi n d o w s下
    注册,并且可以在任何Wi n d o w s开发环境中使用。将这些类型的自定义控件加进D L L中,是考虑到即
    使有多个应用程序要使用这些自定义控件,内存中也只有该控件的一份实例。
    注意其实将自定义控件加进DLL这种机制已经过时,现在,微软使用OLE和ActiveX控件,自
    定义控件已很少见了。
      

  4.   

    摘录一个D5指南的一段话,希望对你理解有用
    动态链接库是程序模块,它包括代码、数据或资源,能够被其他的Wi n d o w s 应用程序共享。D L L的主要特点之一是应用程序可以在运行时调入代码执行,而不是在编译时链接代码,因此,多个应用程序可以共享同一个D L L 的代码。事实上,文件K e r n e l 3 2 . d l l 、U s e r 3 2 . d l l 、G D I 3 2 . d l l 就是核心Wi n 3 2 系
    统的动态链接库。K e r n e l . d l l 负责内存、进程和线程的管理。U S E R 3 2 . D L L 包含了一些程序,是创建窗口和处理Wi n 3 2 消息的用户接口。G D I 3 2 . D L L 负责处理图形。你还会听说其他的系统D L L ,譬如A d v A P I 3 2 . d l l 和C o m D l g 3 2 . d l l ,它们分别处理对象安全性/注册操作和通用对话框。使用动态链接库的另一个特点是有利于应用程序的模块化。这样就简化了应用程序的修改,因为
    一般只需要修改D L L ,而不是整个应用程序。Wi n d o w s 环境自身就是模块化类型的典型实例。每当安
    装一个新设备,就安装一个设备驱动程序(即D L L ),使设备能够与Wi n d o w s 相互通信。
    在磁盘上,一个D L L 基本上类似于一个Wi n d o w s 可执行文件( * . E X E )。一个主要的区别是, D L L 不是
    一个独立的可执行文件,尽管它可能包含了可执行代码。大部分D L L 文件的扩展名是. d l l ,也有的可能
    是. d r v (设备驱动程序)、. s y s (系统文件)、. f o n (字体文件),这些不包含可执行代码。