如何使用Rebase以及bind来重定位和绑定dll

来源:互联网 发布:ms和mrs 知乎 编辑:程序博客网 时间:2024/06/08 01:24

      dll的重定位和绑定技术可以优化应用程序的性能。我们知道,程序性能最本质的提升是算法(这里的算法绝不仅是1+1=2的问题)的改进,其他的改进只是一些配置的优化而已。

     那么重定位和绑定属于哪一种呢?从原理上来说,应该说是属于后者。我们知道dll的默认基地址(image base)是0x1000000,如果应用程序同时载入两个dll映像文件,那么由于这两个dll不可能同时映射到同一个虚拟地址,所以会产生重定位的过程。对于隐式dll链接来说,这会增加应用程序初始化的时间,给用户一种程序反应慢得感觉。而显式链接虽然少去了初始化的开销,但是影响到程序执行时的性能(由于dll可能需要重定位)。

     为了减少每次程序执行时,诸如上述所说的性能开销,我们必须找到一种一次解决,方便万世的方法。dll重定位应运而生。使用VC的Rebase,我们可以给dll设定不同的基地址,使得重定位的过程消失无形,这可以提高程序的性能。那么,到底该如何做呢?比如,有add.dll,minus.dll和可执行模块compute.exe,compute.exe用前两个dll来实现加减法操作。现在,我们使用Rebase对add.dll和minus.dll进行重定位。Ctrl+R,输入cmd,进入Console,输入Rebase -b 0x20000000 add.dll minus.dll,这时,我们用dumpbin /headers来查看add.dll和minus.dll的头部,会发现他们的基地址是从0x2000000开始的某个地址,而且两个基地址不同,也不相交。这样,当我们应用程序加载这两个dll的时候,就不存在重定位的问题啦。

     重定位问题解决了,那么什么是绑定呢?当我们使用dumpbin /imports compute.exe时,我们可以发现,导入的函数只有序号和函数名,那么程序执行时,如何找到函数的地址(即入口)呢?这些工作是由加载程序来做的,他会根据每个dll的导出段的信息来修改可执行模块的导入段,所以,实际加载后,可执行文件的导入段包括了该函数在进程地址空间中的虚拟地址,序号和函数名。这里,我们同样看到了降低程序性能的缺憾。如果,在加载程序的时候,这些地址就已经有了,那么程序的性能不是又可以提升了吗?不错,办法总是有的。不过,这得在Rebase重定位的基础之上来实现,否者,毫无效果。在Rebase后,所有的dll模块都有了独立的基地址(dll之间不交叉),这同时也意味着每一个dll的函数在进程虚拟地址空间中的位置确立了,那么将这些地址写入可执行模块的导入段,将会省去加载程序修改导入段的过程,这样程序的性能又得到提升了,很不错吧。具体做法,Ctrl+R,输入cmd,进入Console,输入bind -u compute.exe即可。

      重定位和绑定的联合使用可以极大地优化程序的性能,这样你写出来的程序看上去总是比不用这种方式的程序跑的快,你说说,如果你是客户,which is your choice!


原创粉丝点击