《Win32动态连接库基址重置技术.docx》由会员分享,可在线阅读,更多相关《Win32动态连接库基址重置技术.docx(25页珍藏版)》请在优知文库上搜索。
1、编辑:Jsz目录:摘要/引言应用程序动态联接库(D1.1.)建立动态联接库理论数据建议其他因素/Win32动态连接库基址重置技术RuedigerR.AscheMicrosoftDeveloperNetwork技术小组摘要本文讨论了MiCrOSOftWindowsNT和MiCroSOftWindows95动态链接库(dynamic-linklibrary,D1.1.)基址重置(rebasing)的若干问题(在本文中,“Rebasing,基址重置”一词指的是在内存空间中改变动态链接库基地址的过程)。随本文章提供了一个应用程序实例和一个动态链接库套件,读者可以从中进行一些比较。引言开发人员常问到的一
2、个问题是,“当操作系统对动态链接库(D1.1.)进行基址重置时,会出现什么效果?基址重置会带来什么损失?有什么办法可以避免这些损失?是否有办法修改代码以减少基址重置所带来的修补(fixup)工作?”由于这些问题很有代表性,所以本文将集中讨论一下加载动态链接库(D1.1.)的有关问题,希望为使用动态链接库(D1.1.)的读者提供一定的参考。事实上,本文给出的结果也许并不太新奇,也不太具有“革命性”,比方说:最好选择较大的动态链接库(D1.1.),而不宜选择一大堆小的动态链接库;确定系统不需要花费很长时间搜索动态链接库;如果操作系统有可能对动态链接库进行基址重置,应尽量避免由此而带来的修补工作(或
3、者也可以使用另一种办法,尽量选定用户基地址,防止基址重置现象的发生)。然而,正如一句古老言语所说的那样,“过程即目标(Thejourneyisthegoal.)w三换句话说,作者在写作本文时,发现了大量的有关动态链接库和内存管理的小问题、小技巧,作者认为,这些问题和技巧是值得与大家分享的。也许,这篇文章更合适的名字应该是“动态链接库点滴”o在本文中,将给出一个作者自己写的样本测试应用程序,此程序用于测试动态链接库的加载时间。本文还将提供一些测试用的动态链接库。公,参考资料附录A:运行测试程序的结果(NT)附录B:运行测试程序的结果(Win95)下一页应用程序您是本站自1999.4.5以来第巨客
4、人!Win32动态连接库基址重置技术RuedigerR.AscheMicrosoftDeveloperNetwork技术小组应用程序用于测试动态链接库(D1.1.)加载时间的测试集结构非常简单,主要包括:使用MiCrOSOft基础类库(FoundationClasslibraries,MFC)编写的PAGETEST应用程序,此程序包含两个线程。第一个线程(主应用程序)建立并拥有默件(mutex)对象。此线程对当前时间进行采样,然后调用1.oad1.ibrary函数,以显式方式加载作者提供的库(本文下一节将讨论这些库)。与此同时,第二个线程等待默件(mutex)对象发送信号。所有的库都由动态链接
5、库的入口程序组成。在动态链接库(D1.1.)入口程序的PROCESSATTACH发送点,默件(mutex)对象发送信号。此时,辅助的应用程序线程被唤醒,在调用1.oad1.ibrary函数之前,计算采样时间和当前时间之间的差值。这个时间差值大致上就是D1.1.装入内存所需的时间。MFC应用程序有一个反复加载和卸载D1.1.的选项(50次),通过反复加载,可以计算出有意义的平均加载时间。编辑:Isz目录:摘要/引言应用程序动态联接库(D1.1.)建立动态联接库文章不需要讨论应用程序的特性,因为本文中使用的程序都是简单的MFC应用程序,所有的相关代码都存在于显示类中。显示类由CEaSyOUIPUt
6、vieW函数引出,用于提供简单的显示结果。(欲知进一步的细节,请参阅WindowsNTSecurityinTheoryandPracticew,WindowsNT安全性理论与实践)读者应该注意,这种经验式的测试方法有很多缺陷,因此测试结果有可能与实际结果相背离,这主要因为: 作者假设时间抽样机制是有效而可靠的,抽样力度足够细。(作者使用了系统性能计数器) 作者假设线程切换机制是连续有效的,对唤醒辅助线程所需时间没有非常不良的影响。 测试结果在很大程度上,依赖于底层硬件(也就是说,下列一些因素也会对测试结果产生影响,如运行测试程序的计算机速度、所使用的处理器数目、硬盘控制器的速度、等等)。 测试
7、结果使用特定版本的软件进行抽样。(操作系统版本、C运行时间库版本、等等。) 通常情况下,大多数动态链接库都是隐式加载的,而不是显示加载的。这就要求作出如下假设:隐式加载D1.1.与显示加载D1.1.所用的时间一样长,相应的其他参数也相同。更糟糕的是,作者所得到的数据有时相差很大。因此,读者应该有保留地接受这些结果。在测试结果中,更有参考价值的不是加载所需的绝对时间,而是相对时间。换句话说,重要的是调整某一参数对加载行为的影响,以及不同策略之间的加载结果比较。如果读者希望在自己的计算机上重建测试结果,可以按照下一节将讨论的动态链接库定位指令,运行PTAPP.EXE,并在MUItiPIeTeSt菜
8、单中,选择RUnl1TeStS选项。上一页下一页摘要/引言动态联接库(D1.1.)您是本站自1999.4.5以来第巴J客人!Win32动态连接库基址重置技术RuedigerR.AscheMicrosoftDeveloperNetwork技术小组理论数据建议其他因素/参考资料附录A:运行测试程序的结果(NT)附录B:运行测试程序的结果(Win95)编辑:Isz动态链接库下面是动态链接库与加载时间有关的一些性质: 动态链接库的大小。 需要重定位的条目数量。 动态链接库是否初始化C启动代码。 动态链接库是否输出符号。 动态链接库是否与其他库隐式链接。 操作系统需要多长时间,才能重定位可执行的动态链接
9、库。除了上述因素以外,还有一些独立于动态链接库的因素,也决定着动态链接库加载速度的快慢。例如,底层操作系统、当前计算机上总的工作负荷、应用程序的工作集、动态链接库是否需要基址重置、等等。为简单起见,作者给出18个小的动态链接库(其中有些并不太小),这些D1.1.几乎代表了以下特性的全部组合: 动态链接库大小(可以大也可以小) 如果是大的动态链接库,是否需要修正加载时间 C运行时间支持(没有支持、隐式链接的、显示链接的) 动态链接库输出的符号(yes或no)作者在同一台机器上,在WindOWSNT版本3.51和WindOWS95环境下,将全部18个动态链接库通过各自首选的虚拟地址区,加载到各自首
10、选的基地址中。每个测试程序也首先将动态链接库定位到当前目录中,然后,沿着路径下行搜索,测试将动态链接库定位到当前搜索到的目录中,操作系统所需花费的时间。如前所述,每次测试运行50此,得到统计平均值。作者的第一个发现是,在WindoWSNT环境下,任何给定的动态链接库的初始加载时间,平均是在以后加载同一个动态链接库所需时间的三倍。这种现象是由WindowsNT内存管理设计的副作用造成的:一旦初始加载了某一动态链接库,卸载后,属于此动态链接库映象的页仍然存在内存中;这些页被放在等待列表中(等待列表是系统为丢弃的页维护的一个列表,如果原来的应用程序又需要此列表中的页,或新的应用程序需要访问列表中的页
11、,这些页可以被重新起用。)读者如果想了解有关等待列表的进一步信息,请参阅HelenCuster的InSideWindowsNT(WindowsNT内幕)一书的194页到196页。目录:摘要/引言应用程序动态联接库(D1.1.)建立动态联接库理论工具数据建议其他因素/参考资料附录A:运行测试程序的结果(NT)附录B:运从等待列表页中重载动态链接库的页,比从磁盘上重载有关页效率高的多。随着时间的推移,有关的页会从等待列表中移到自由列表中。如果在加载初始动态链接库和加载后续动态链接库之间,有很多内存分配和内存访问操作,两种情况下加载动态链接库所花的时间将不会有太大差别。为模拟上述行为(一定通过多次测
12、试,取得加载动态链接库时间的统计平均值),作者加入了一个选项,此选项允许应用程序尽可能多地占用内存,使等待列表尽快用完。伴随着WindoWSNTReSoUrCeKit,微软将提供一个小小的实用程序,此程序可以强制将一页从等待列表中取行测试程序的出,此程序是C1.EARMEM.EXE0实用上述方法确实十分有效,但遗憾的是,作者释放了所占用的内存之后,加载时间一下变成平均时间的20倍一一初始加载时间的7倍。这种现象使作者陷入了一个两难境地:一方面,作者希望得到在正常工作条件下,加载动态链接库的可靠的统计平均时间;另一方面,作者所能得到的唯一的可靠的、一致的时间不是在正常工作条件下得到的。于是,作者
13、使用了如下的冒险策略(但却是合理的方法),解决了这一两难问题:假设初始加载时间和随后的平均加载时间之间的关系是固定的,将测试结果建立在比较加载动态链接库的平均时间的基础上。使用这种办法,在正常工作情况下,所得的比较结果仍然是有意义的。读者如果希望重建动态链接库、加入自己的动态链接库变量、或者只是想了解一下作者如何建立了18个动态链接库,可以继续阅读(或浏览-下)下一小节。否则,可以跳过这小节,直接阅读“理论”一节。上一页下一页应用程序建立动态联接库您是本站自1999.4.5以来第回客人!Win32动态连接库基址重置技术RuedigerR.Asche、编辑:IszMicrosoftDevelop
14、erNetwork技术小组目录:摘要/引言应用程序动态联接库(D1.1.)建立动态链接库使用ViSUaIC+版本2.2产生makefiIe,可以建立动态链接库。读者可以在PAGETEST子目录下附加的样本代码中,找到相应的工程文件。全部18个动态链接库都是由相同的工程文件产生的;读者可以建立自己的动态链接库原始版本(未经调试的版本),然后使用以下的命名规则,将产生的可执行代码复制到新的位置。PTAPP样本应用程序要求在动态链接库的名字中,包含D1.1.内容信息。动态链接库名字的每一个字母代表一种属性,对应的命名规则如下:第一个字母代表动态链接库是小库(不包含任何数据)还是大库(包含100,00
15、0个静态数据元素)。此位置如果是S,表示动态链接库是小库;此位置如果是1.,表示动态链接库是大库;F表示所有的100,000个数据元素都初始化为可重定位的自串,当动态链接库进行基址重置时,字串的地址必须在加载时进行调整。注意:有100,000个可重定位的字串并不表示一定要进行100,000次重定位。对于ViSUaIC+版本2.x来说,还存在一个问题,VisualC+的连接器将可移植的可执行文件中的可重定位项数目限制在64K之内。因此,如果在某个名字以F开始的动态链接库中,运行.EXE头实用程序,例如YAHU,用户会发现只有34K可重定位的地址。这一问题将在新版本的VisualC+中得到解决。第二个字母表示动态链接库是否支持CRT代码(Cnm-time)。如果此位为N,表示D1.1.有一个自定义入口点,不调用CRT初始化代码(CrUn-time);如果此位为C,表示动态链接库的人口地址是DnMain,可以隐式地初始化CRT(CrUn-time);如果此位为D,表示动态链接库有一个自定义的入口地址,调用_CRT_1NrE动态地初始化CRT(Crun-time)库。最后,第三个字母如果是N,表示动态链接库不输出任何符号;如果是E表示输出一个函数。其余的字母现在还未指定