利用DelayLoad来优化应用程序的性能及拦截API
在 1998年12月的MSJ出版刊物中, Jeffrey和我写了关于 在 vc6中使用DelayLoad 功能的专栏.最终结果,是证明了它是多么cool.但是,不幸的是,还有很多人不了解DelayLoad,他们以为这个新特点是 最新版本的WINNT才有的. 在开始的时候,让我重申一遍:DelayLoad不是最新的操作系统带的特有功能,它可以在任何win32系统中起作用.我将写一个简单例子来说明. DelayLoadProfile, 实现了一个很小功能,很多程序都可以得益于它. 预览: 通常的,当调用一个dll中的函数时,连接器会将dll和函数加入你的可执行文件.最后,所有引用的函数会放在imports段中. 当加载该程序的时候,win32程序加载器会扫描所有imports段的每个dll.加载,和重新定位imports段的所有函数,将信息写入 引入地址表(ImportAddress Table, IAT).简单说来,IAT就是一个函数指针的表.调用该 引入函数的时候,就到IAT中去找. 那么,DelayLoad的机理是什么呢?当你为一个Dll进行"DelayLoad"的时候,连接器不将原来的值放入imports段,相反,它为每个DelayLoad的引入函数的名称和地址,生成一个小的根区, 备份下来。第一次引用的时候,它调用LoadLibrary加载Dll,然后,它调用GetProcAddress取得该函数的地址。最后,改写自己在IAT的值,以便以后的程序可以直接调用. 上面的是简化的步骤.实际上,根区是一小段代码,它以静态的方式连接到可执行文件中.代码在delayimp.lib中,必须被 连接程序引用.并且,该代码要足够智能,当一个函数第一次被引用的时候,要调用LoadLibrary,以后调用就不用引用了. 和引用Dll相比,DelayLoad不会加太多的时间和空间,这种方式 调用LoadLibrary只会引起稍微一点点的性能损失.每次程序启动,在针对引入表的函数地址定位的时候,依次对DelayLoad引入的调用GetProcAddress,相对于Win32加载器来说,所损失的性能也可以忽略不记. 然而,DelayLoad带来的好处也是不可比拟的.例如:如果你的程序从来没有 从Delay调用引入的函数,Dll的第一次是不会被加载的。有时候,这个情况的出现频率出乎你想象。假如,你的程序中,包含打印的代码,毫无疑问,即使用户没有使用打印功能,你的程序也一定要加载winspool.drv。在这种情况下,使用DelayLoad,你就不必加载和初始化Winspool.drv. 另外一个好处就是:DelayLoad可以避免调用某些目标平台不存在的API。例如,假如你的程序需要调用AnimateWindow,这个API在Win2000和Win98中存在,但是在Win95和WinNT4中,就不存在,假如你用常规的方式调用AnimateWindow,那么,你的程序将不能再早期的平台中运行。然而,你可以用DelayLoad进行对AnimateWindow的加载检查。这样,你就不必改写你的代码为LoadLibrary和GetProcAddress的方式了。 DelayLoad是很容易使用的。当你决定哪个dll你想使用DelayLoad,只需要简单的增加/DELAYLOAD:DLLNAME。其中,DLLNAME是相关的DLL文件名。你还需要增加DELAYIMP.LIB到连接库中,你也需要原来的LIB,例如,SHELL32.LIB。把全部放到一块,连接的命令就如下: SHELL32.LIB /DELAYLOAD:SHELL32.DLL DELAYIMP.LIB 很不幸,Visual Studio 6.0 IDE 不提供一个简单的方法去实现一个Dll的DelayLoad。所以,你必须手工加入:/DELAYLOAD:XXX 命令行到 "Project settings"->"Link"->"Project Options"中。 什么时候需要DelayLoad: 当你有小的工程,它调用了多个dll,就是一个好的DelayLoad候选例子。然而,工程可能在以后由于其它开发者的加入而变大,很容易丢失调用dll的跟踪。我通常用sdk中的depends.exe。一个只有少数函数要引入的dll就是一个好的开始。 然而,我想找到一个简单的,自动的方法来跟踪。于是,出来了DelayLoadProfile程序。它是一个exe,可以监视你的exe文件 |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |