百度文库-让每个人平等地提升自我!
1
DLL陷阱是一个恶梦,是一种相当奇怪的问题。
相信很多读者都有这样的经验,如果你的软体今天原本运作顺畅,当你安装某个新软体
之后,突然间电脑就无法运作了。这绝对不是你的硬体有问题,也不是应用程序的问题,而是作
业系统设计上的缺失,这样的问题层出不穷,这通常是因为新的应用程序版本覆盖掉共享的程序
库(DLL),而且往往修改了一些现存应用程序所必需的「bug」,这个缺失有了一个名字叫做DLL
Hell(DLL地狱)。开发人员与系统管理者(以及使用者)面临最大的挑战就是版本更新的问题,他
们花很多时间在Windows登录档(Regedit)上试着解决其问题而吃尽苦头。
.在的世界里,软体元件再也不需要登录(Registry)了!NETFramework包含了一
些功能,可以实际消除「DLLHell」的问题,一项称之为「side-by-side」开发模式的新功能。
DLL&DLLHell
为什么要使用DLL(DynamicLinkingLibrary)-动态链接库?
微软当初为Windows设计动态链接库主要是撷取它的两项优点:一是动态连结、一是
资源共享。资源共享的例子相当显而易见,例如之前曾经提过Windows有三个核心的动态链接
库:Kernel主要是负责系统和应用程序的记忆体、行程和执行绪等等的管理工作;Ur主要负
责使用者介面和讯息的传递;GDI则负责系统的任何图形绘制、显示等工作。而这些动态链接库
所提供的任何函数都可以在必要的时候,让每一个Windows环境底下的执行档使用。因为DLL
具备节省记忆体的特性,因此自从Windows3.1版以来,它就逐渐成为Windows程序设计的主流
˙动态链接库可以资源共享
许多大型软体厂商的众多软体产品可能都会有许多可以共用的模组,如果每一套软体
各自拥有一份这些可以共用的模组,不仅会造成磁碟空间的浪费,还会让维护这些模组的工作变
的既复杂、又凌乱。最好的方法就是仅保持一份程序码,然后透过共享的方式让其他自家的应用
程序也可以存取其中共用的模组。共用模组的方法之一就是将模组制作成动态链接库,然后透过
百度文库-让每个人平等地提升自我!
2
软体的安装程序复制到电脑,那么只要安装了其中一套软体之后,其他自家的产品就可以互相共
用这一套动态链接库。
假设有一函数库X供三个应用程序A、B、C使用,如果函数库为目的码或原始程序
码,则程序编译之后,函数库X将会各自成为执行档A、B、C的一部份,而将来如果应用程序
A、B、C同时执行,函数库X也会各自占用一份记忆体,显然这是比较浪费记忆体的方式。
如果函数库为DLL形式,则编译之后,函数库并不会成为执行档的一部分,而将来如
果应用程序A、B、C同时被执行,则系统只会载入一份函数库让程序A、程序B、程序C共用,
如图。
Figure:程序与DLL的共用架构图
˙动态链接库节省记忆体空间
动态链接库的资源共享可以节省磁碟空间,而动态载入的连结方式则可以节省记忆体空
间。动态链接库采用动态载入的连结方式,动态载入让程序档在需要相关的函数或资源的时候,
才载入放置在动态链接库里面的函数或资源,这种方式将可以有效地使用记忆体。不论是节省磁
碟空间或记忆体空间,都是希望利用动态链接库所提供的共享函数与系统资源的方式,降低整个
Windows环境对于硬体设备的需求。
百度文库-让每个人平等地提升自我!
3
DLL的问题-DLLHell
˙动态链接库到底出了什么问题?
其实DLL的优点(程序码共用、节省记忆体),正是其缺点的起源。原本是立意良好的
DLL,有一天会变成DLLHell,恐怕是当初DLL的设计者所始料未及的。
而之所以会出现DLLHell,也是因为动态链接库可以与其他程序共用函数、共享资源
所引起,可谓「成也共用、败也共用」。此话怎讲呢?为了要让其他程序共用动态链接库所提供
的函数或资源,动态链接库的设计者必须相当谨慎地、缜密地考虑到功能的一致性、回溯相容等
细节问题,否则一旦程序所使用动态链接库没有提供所预期的功能,那么使用者就会为此而掉入
地狱了。
但是要完全考虑到一致性或回溯相容,实在是困难重重,就算真的要做到,也会让利用
动态链接库的软体厂商付出相当的成本;但,有必要付出这些成本吗?想想现今的电脑执行环境,
与当初微软设计动态链接库的时候已经有相当、相当大的变化。现在的硬体比起当初已经便宜太
多、太多了,个人电脑的记忆体都是从64MB起跳,配备128MB记忆体的电脑更是比比皆是,
而硬碟容量更是以GB计算。在如此的硬体环境之下,Windows程序设计师还需要这么刻苦地考
虑共用的问题吗?而且动态链接库的动态载入,其实已经替Windows系统节省了不少系统资源,
因此微软也重新调整动态链接库的设计理念,而且也针对作业系统进行改善,希望不要再有任何
使用者掉入因为共用动态链接库而起的地狱深渊。
˙数种DLLHell的状况
让我们想一想,如果某一副程序或物件类别有90%符合我们的需求,却有10%不符合,
怎么办呢?对副程序来说,大概只有修改「原始程序码」一途。
假设程序A会使用物件X,在程序A安装到系统时,会同时安装物件X,假设另一个
百度文库-让每个人平等地提升自我!
4
程序B也会使用到物件X,那么程序B直接复制到硬碟中即可正常运作,因为物件X已经存在
于系统中,这听起来很好,因为程序A与程序B可以共用物件X。然而对程序A来说,原本在
安装后,执行得好好的,却可能在未知的一天变成无法执行,这就是所谓的DLLHell。以下为
描述DLLHell的两种状态。
状况1.动态链接库没有善尽回溯相容的责任
如果程序A使用的是1.0版的物件X,而程序B使用的是2.0版的物件X(通常是因为
程序B开发的时间较晚,使用较新的版本),结果会怎样呢?结果在程序B被安装到系统时,物
件X2.0版也必须安装到系统中,此时系统中1.0版的物件X将会被2.0版所取代。
在大部分的情况下,物件X2.0版相容于1.0版,所以程序A依然可以正常运作,但有
时候却会出现2.0版及1.0版不相容的情况,此时程序A便无法正常执行了。此种DLLHell
的起因则是的设计者,原因在于动态链接库没有善尽回溯相容的原则。试着想想需要
所提供的功能,但是在新版的里面,功能竟然被取消了,这时候也极可能发生DLLHell。
但是诚如之前所讨论,有时往往很难保证百分之百的回溯相容,而且目前个人电脑的
硬体配备已经不再像以前简陋,因此微软也提出了所谓Side-By-Side的动态链接库,让程序都能
拥有自己专属的动态链接库,进而减少共用动态链接库以避免这种DLLHell的发生。
状况2.动态链接库善尽回溯相容的责任,但动态链接库本身出现bug
另一种情况,物件X的提供者确实考虑到版本相容的问题,而根据物件的规格来看,
新旧版也的确相容,但程序A使用新版的物件X就是有问题,毕竟程序A并没有与新版的物件
X一起运作过,谁知道会发生什么情况?
百度文库-让每个人平等地提升自我!
5
Client
ServerDLL
()
ServerCodes
程序A用X
1.0
(X1.0)(原始版
本)
PublicSetValue(ByValValueAsInteger)
IfValue<0Then
Value=0
EndIf
m_Value=Value
EndProperty
程序B用X
2.0
(X2.0)(更新
版本)
PublicSetValue(ByValValueAsInteger)
'Fixthebug
IfValue<0Then
umber:=APP_ERROR,
Description:="NegativeValue"
EndIf
m_Value=Value
EndProperty
如上表所发生的不幸的事,纵使X2.0的开发人员小心翼翼透过VB6.0的二进位相容模式控
制DLL版本,且所有的内部GUID值与方法和参数都完全相同,由于X1.0之中有一个名为
Value的属性名称,当此一属性设为负数时,该属性就会变成零,但却不会出现错误讯息。这个做
法是错误的,X2.0版将此臭从解决了-若将Value属性设为负数,则会抛出错误。
当程序B以X2.0散布时,这支程序B当然也可以正常运作。不过,如果将X2.0
安装在系统之中,程序A会当掉。之前程序将Value属性设为-1不会有问题,但现在会出现执
行时期的错误。同时程序A的开发人员并未在这设计错误检视的机制。
在许多真实的案例中,要善尽二进位相容模式控制DLL版是非常困难的,亘何况即使
是二进位相容模式控制DLL版本还是有可能造成DLLHell。
如何解决DLLHell的问题
自我描述的Asmbly(Self-describingAsmbly)
百度文库-让每个人平等地提升自我!
6
Asmbly(组合)是简化部署与版本管理的关键。Asmbly是部署与版本管理的基本
单元,其中包含一群资源(Resource)与型别(Type),以及它们内含的Metadata,同时也包括
此组合在建造时所依赖的其他组合的版本资讯。有了独立完整的组态资讯,同一组合的不同版本
也可安装在同一部机器上,搭配共通语言执行环境具备根据各组合的组态资讯,载入正确版本的
依赖组合(DependentAsmblies)的能力,安装与解除安装的过程,就如同复制档案与删除档
案一样单纯,以往因先后安装彼此覆盖而产生的所谓“DLLHell”的版本失控的现象不复存在。
-DescribingAsmbly可包括多个档案
Metadata(定义)是Asmbly能自我描述的关键。Metadata是编辑器在产生执行码时,
伴随产生的定义性资讯,举凡元件所使用的型别、属性、方法、事件甚至辅助与备注等资讯都可
包含在内,而且保证与执行码的一致性,完全取代并且超越了传统分离式的IDL(Interface
DefinitionLanguage)档案与型别库(TypeLibrary)所扮演的功能,同时元件服务要求与执行所
需的资讯皆动态来自Metadata。.asemblydirective作为辨识asmbly本身,.asmblyextern
directives定义此asmbly所依赖的其他Asmblies。
百度文库-让每个人平等地提升自我!
7
Figure.可使用ILDisasmbler(Ildasm)呈现DLL的metadata
简化的部署与版本管理
˙Application-PrivateAsmblies(IsolatedAsmbly)
Application-PrivateAsmblies(or被隔离的asmbly)只能被一个应用程序所使用-它不能被其
他的应用程序所共用。隔离asmbly让程序开发者有着对应用程序绝对的控制权,这也是
应用程序的预设方式。
开发好的Application-PrivateAsmblies要在另一个环境进行安装时,手续只有
一个,就是CopyAndPaste。只要把编译好的程序,无论是EXE执行档、DLL元件、
的.aspx网页或WebService的.asmx档,全部都是以复制/贴上的方式部署在和应用程序相同的目
录,这些档案复制完成后,不需额外注册或设定。程序执行时,如果需要额外的元件,首
先会自本身执行档下的同一目录开始寻找,因此,每套应用程序预设都是使用本身同一目录下的
元件,不同应用程序间不会相互干扰,也消除了DLLHell的困扰。(注:TheCLRfindsthe
gissimplyamappingoftheasmblynametothe
nameofthefilethatcontainsthemanifest.)
百度文库-让每个人平等地提升自我!
8
˙SharedAsmblies-Sidebysideexecution(并排执行)
然而,应用程序共享asmbly还是有其必要性,因为让每个应用程序都有自己一份
copy(如,commonWebFormscontrol)是件很奇怪的
事。
为了解决DLLHell的问题,增加了一种新的技术,称为Sidebysideexecution,
意思是应用程序可以拥有各自版本的DLL,例如程序A使用版本1.0的物件、而程序B使用版
本2.0的物件,1.0版与2.0版的物件可以同时在系统执行。
透过Sidebysideexecution的技术,应用程序只要安装成功之后,就不用担心DLL更新
版本,或规格的改变,因为就算DLL改朝了,应该程序也不用换代。以下简述Sidebyside
execution的过程图及应用步骤:
sforimplementingstrongnames
akeypairusingtheStrongNametool().
Sn–
严格名称(Strongnames)是一种在架构下可减少DLL陷阱的功能
百度文库-让每个人平等地提升自我!
9
(注:Theauthorofanasmblygeneratesakeypair,signsthefilecontainingthemanifestwiththe
privatekey,pairis
pasdtothecompilerusingthecustomAsmblyattribute)
asmblywithastrongnameandversionnumber:
,
lAsmblytoGlobalasmblycache(GAC)
gacutil/i:
(注:meworkSDKdocumentationforafulldescriptionoftheoptionssupportedby
gacutil.)
百度文库-让每个人平等地提升自我!
10
Figure:GlobalAsmblyCache
Step4.应用程序与Asmbly的版本系结(VersionPolicy)
提供有组态设定机制可以控制Asmbly的系结,故在程序中可以载入相关Asmbly的
升级版本。组态设定机制是由XML设定档来负责,透过这种安全机制可以控制程序的安全、版
本以及远端的功能。每一个应用程序可以有XML程序设定档来指定应用程序所要系结Asmbly
的不同版本
程序设定档的档案名称为程序名称加上.config副档名,如。
例如以下范例设定档会载入MarineCtrl版本5.0.0.1而非版本5.0.0.0
百度文库-让每个人平等地提升自我!
11
Summary
meworkNETAsmbly自我描述与版本管理功能让zero-impact的部署安
装成为可能,同时也终结了DLLHell。
Application-PrivateAsmblies(or被隔离的asmbly)只能被一个应用程序所使用-
它不会被其他的应用程序所影响。隔离的asmbly让程序开发者对应用程序有着绝对的控制
权,开发好的Application-PrivateAsmblies只要部署在和应用程序同一目录即可。
透过Sidebysideexecution的技术,应用程序只要安装成功之后,就不用担心DLL更
新版本,或规格的改变,它允许一个asmbly的多个版本在一个机器上同时被安装并执行,
而且每一个应用程序都可以要求和不同的Asmbly版本系结。
mework纪录应用程序版本资讯,并在执行应用程序时使用此资讯载入应
用程序所需依赖的正确版本的Asmblies
本文发布于:2022-11-25 08:51:02,感谢您对本站的认可!
本文链接:http://www.wtabcd.cn/fanwen/fan/90/17489.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |