Windows 64位平台和.Net Framework在64位平台上的一些Tips (一)

来源:互联网 发布:中经网统计数据库 编辑:程序博客网 时间:2024/05/21 06:22

关键词: X64, x32子系统, .Net Framework

本文适合的读者:
对64位Windows平台刚刚入门,并且对.Net Framework有一些了解的技术人员。

 

看的出来,64位Windows操作系统和.Net Framework的设计者在对32位软件的兼容这一问题上是费足了脑精的(当然这离不开64位CPU本身对32位指令集的虚拟支持, 不过有些CPU已经把对32位环境的支持完全移到了软件层去虚拟实现, 比如新一代的Intel 安腾Itanium 处理器)。在很多情况下,64位Windows系统看上去已经很像跨32-64的架构了。但同时也难免带出很多麻烦。有很多细小的地方值得我们注意。我就曾经很多次对着电脑不知所措。事情总是分两面讲,一方面,技术总还是有缺陷的,另一方面,是我们自己学习的还不够。

 

64位Windows实现32位兼容的方法是,在64位系统中嵌入一个虚拟的32位“子系统”(中规中矩)。遇到32位的应用程序,就把它放在32位子系统中去运行。这个过程很多情况下对用户是透明的。为了达到这一点,很多基础的应用程序库DLL都需要有两份,一份供给32位软件使用,一份供给64位软件使用。他们分别位于C:/Windows/System32和C:/Windows/SysWOW64中。这里很容易产生疑惑的是System32中存放的是供64位使用的应用程序库和工具软件,而SysWOW64中存放的则是供32位使用的版本。不要被他们的名字搞混了,使用System32命名64位文件夹是由于习惯原因。而WOW64指的”Windows on Windows 64”。

 

实验:32位子系统初体验(你需要一台64位的机器)

1) 在一台64位机器上,打开一个普通的的命名行窗口,它应该位于C:/Windows/System32/cmd.exe2) 在其中输入 echo %processor_architecture%
3) 打开32为命令行窗口,C:/Windows/SysWOW64/cmd.exe,并在其中输入和之前相同的命令

你会看到不同的结果(我不保证在所有的Windows操作系统版本上都是这样)。在我的AMD64 Windows2008 机器上我得到的结果分别是: AMD64和x86。 我们可以看到在32位子系统中,系统试图屏蔽真实的情况(即使我的cpu是64位的,它仍然告诉我它是x86)。这种善意的谎言有时候给用户带来快乐(就像我们总是怀念旧时的简单生活一样),但有时候也会给人带来苦恼(当你真已经知道的太多并且不可救药的时候),我在下面的文章中会再提到这一点。

.Net Framework 的加入进一步弱化了平台相关性。如果你曾经接触过.Net的托管代码(Managed Code)你会知道,.Net 在默认情况下将托管代码编译成.Net中间语言(MSIL, Microsoft Intermediate Language) 当软件真正运行的时候 再根据CPU的架构进行再一步快速编译,生成与当前CPU兼容的机器语言并即时运行。这个过程对用户是完全透明的。这样做看上去天衣无缝了,但可惜的事,不是所有的代码都是托管代码,不管是由于市场,历史,还是性能的原因。所以这个本来的理想世界就变得复杂了。

 

如何将托管代码编译成仅支持x64或者x86的程序集

.NET在默认情况下将托管代码用”Any CPU”来编译(除非在代码中混有非托管代码的时候它不能这么做)。然后CLR在运行时决定到底是在什么CPU平台下运行,并且进行针对这一平台进行进一步编译。

有时候我们需要指定我们的程序集是仅能在32位或者64位环境中运行的。利用Visual Studio做到这一点很容易。在Visual Studio中创建任意一个托管项目,这里以C# Console Application为例。在Solution Explorer里面右键点击项目文件,在菜单中选择“属性”,在项目属性页里面选择”Build”页面。你将会看到,默认的platform target 是“Any CPU”。这就意味着在默认情况下,项目会被编译成MSIL中间语言程序集。点开下拉菜单, 你会看到你可以选择的CPU架构的列表:

 

cpuselection

 

你可以自由选择将你的代码编译成适合哪一种处理器的程序集。从上图中可以看到,虽然我的CPU是AMD64(x64)的。但是Visual Studio仍然给出了Itanium的选项。确实,即使在AMD64的平台上,Visual Studio也允许我将项目编译成本平台不支持的CPU架构(还比如,我可以在x86机器上将代码编译成x64)。这样做的好处是,如果你需要不同平台版本的程序集,你只要在一台机器上把你的代码编译成适合不同cpu架构的多份,而不必把一份代码拿到许多台机器上去编译。但是,如果你试图运行你编译出来的程序集,或者把调试器选择的CPU 也换成本机所不支持的CPU, 你会看到下面的结果:

 

debuggercpu

 

用”Any CPU”编译和用x86编译生成的程序集其实只有很小的区别:只是x86编译的程序集的文件头的32位标志位被设成了1(除此以外还有一些其它细小的差别)。他们都是PE32格式的程序集,而x64程序集则是PE32+格式。在64位环境下,MSIL程序集(以Any CPU编译的程序集)可以顺利运行的原因是,CLR在将其进一步编译之后,可以把它作为PE32+来对待。

 

事实上,在纯托管代码的情况下,借助.Net工具Corflags.exe, x86程序集和MSIL程序集甚至可以互相转换。因为他们本来就没有本质区别,只要改变32Bit标志位就可以了。在下一篇中,我会更具体的介绍Corflags.exe.

期待。。。。。