CLR via C# 第1章 CLR执行模型加载CLR
程序集或者是一个可执行的应用程序,或者是一个包含一组类型的DLL,这些类型供可执行的应用程序使用。CLR负责管理包含在这些程序集中的代码的执行。这意味着主机上必须安装.NET Framework。
如果机器上安装了.NET Framework,则在%SystemRoot%\System32目录下将包含MSCorEE.dll文件。一台机器上可以同时安装多个.NET Framework版本。使用下面这个路径,可以在注册表中查看安装了哪些版本。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP.NET Framework SDK自带的命令行工具CLRVer.exe可以显示安装的所有CLR的版本。
如果程序集只包含类型安全的托管代码,你编写的代码可以在32位和64位的Windows版本中运行,不需要更改任何代码。事实上编译器产生的EXE/DLL文件既可以运行在32位Windows,也可以运行在x64和IA64等64位版本的Windows上。也就是说一个文件可以在任何安装了相应.NET Framework版本的机器上运行。
在极少数情况下,开发者会编写在特殊版本的Windows下运行的代码。通常是在使用unsafe code或需要与面向特定CPU架构的非托管代码进行互操作时。C#编译器提供了一个/platform命令行选项。该选项允许指定结果程序集是运行在x86机器(32位Windows)还是x64机器(64位Windows),或Intel Itanium机器(64位Windows)。如果没有指定平台,默认为anycpu。Visual Studio用户可以在项目属性页中设置项目所面向的平台。
C#编译器根据选项生成包含PE32或PE32+ header的程序集,同时还包括所需的CPU架构(或agnostic)。微软发布了两个SDK命令行工具,DumpBin.exe和CorFlags.exe,可以检查编译器生成的托管模块的头信息。
当运行一个可执行文件时,Windows检查EXE文件的头,来决定应用程序是需要32位还是64位的地址空间。PE32头的文件可以运行在32位或64位的地址空间,PE32+头的文件只能运行在64位的地址空间上。Windows还检查内嵌于头中的CPU架构,来确保其与计算机中的CPU类型相匹配。目前,64位版本的Windows提供了一项技术,允许运行32位Windows应用程序。该技术被称为WoW64(Windows on Windows64)。它还能模仿x86指令集,允许基于x86本地代码的32位应用运行在Itanium机器上,尽管性能有很大损失。
下表显示了两个内容。1)当你指定不同的/platform命令行选项时将得到何种类型的托管模块。2)应用程序如何在不同版本的Windows中运行。
在Windows检查EXE文件头并决定是创建32位、64位还是WoW64位进程后,Windows将x86、x64或IA64版本的MSCorEE.dll加载到进程的地址空间中。在x86版本的Windows中,x86版本的MSCorEE.dll位于C:\Windows\System32目录下。x64或IA64版本的Windows中,x86版本的MSCorEE.dll位于C:\Windows\SysWow64目录,64位版本的位于C:\Windows\System32目录(为了向后兼容)。然后,进程的主线程调用MSCorEE.dll中定义的方法。该方法初始化CLR,加载EXE程序集,然后调用它的入口点方法(Main)。这样托管的应用程序就建立并运行了。(可以在代码中使用Environment的Is64BitOperatingSystem或Is64BitProcess属性来检查是否运行在64位版本的Windows或运行在64位的地址空间中)。
如果一个非托管应用程序调用LoadLibrary来加载托管的程序集,Windows将加载并初始化CLR(如果还未加载的话)。当然在该场景中,进程已经创建并运行,这将限制程序集的可用性。如,使用/platform:x86编译的托管程序集不能被64位的进程加载,反之,一个使用同样的选项编译的可执行文件将以WoW64的形式被64位版本的Windows加载。
CLR via C# 第1章 CLR执行模型加载CLR