CLR via C# FOURTH EDITION(三)

来源:互联网 发布:小企业财务会计软件 编辑:程序博客网 时间:2024/04/30 09:59

加载CLR

每个你生成的程序集可以是一可执行的程序或者是包含了一组可以被可执行程序调用的类型的DLL。当然,CLR负责管理这些程序集中包含的代码运行。这意味着.NET Framework必须被安装到本地机器上。微软创造了一个可重分配的包(redistritribution package)让你可以免费的分发并安装Framework到你的客户的机器上。一些版本的Windows已经打包安装了Framework。


通过查找 %SystemRoot%\System32 目录下的 MSCorEE.dll 文件可以得知是否安装了.NET Framework。(*...你真的想不到更简单的方法了???)这个文件存在的话.NET Framework就是已经安装了。However,一台机器可以同时安装几个版本的.NET Framework。如果想要确认安装了哪个版本的.NET Framework,检查一下目录的子目录:

%SystemRoot%\Microsoft.NET\Framework

%SystemRoot%\Microsoft.NET\Framework64


.NET Framework SDK包含了一个叫CLRer.exe的命令行工具可以显示机器上安装的所有的CLR版本。这个工具还能显示本机当前运行的进程使用的CLR,使用 -all 命令开关或者用进程的ID指定你感兴趣的进程。


在我们开始看CLR如何加载之前,我们需要花点时间讨论32位的Windows和64位的Windows。如果你的程序集文件只包含类型安全的托管代码,你的代码可以在32位和64位Windows上运行。在这两个版本上运行不需要修改源代码。事实上,由编译器最终生成的EXE/DLL文件应该在x86和x64版本的Windows上都能正确工作。另外,Windows Store 应用程序或者类库可以在Windows RT 的机器(使用ARM CPU的机器)上运行。换句话说,一个文件可以在任何机器上运行,只要这台机器安装了对应版本的.NET Framework。


在极少数的情况中,开发者需要写一些只能在特定版本Windows下运行的代码。开发者可能在使用不安全代码时或者与针对特定CPU架构的非托管代码进行交互操作的时候会这么做。为了帮助这些开发者,C#编译器提供了一个 /platform 命令行开关。这个开关允许你指定最终程序集只能在x86的机器上运行或只能在x64的机器上运行,x64的机器只能运行64位Windows,ARM的机器只能运行32位 RT Windows。如果你没有特别指定一个平台,默认的是任何CPU,这表示最终的程序集可以在任何版本的Windows上运行。VS的用户可以通过打开项目的属性页面指定平台,点击 Build 选项卡,在 Platform Target 列表中选择设置(见图)。


在上图中,你会注意到一个 Perfer 32-bit 的选择框。这个选择框只有在项目类型为可执行并且指定平台是任何CPU时才是可选的。如果你选择了Perfer 32-bit,VS的C#编译器会指定开关 /platform:anycpu32bitpreferred。这个设置表面这个可执行程序即使在64位的机器上运行也应该作为32位的程序运行。如果你的程序不需要为64位进程提供额外的内存,那么这是一个典型的好办法因为VS不支持64位应用程序的编辑运行。另外,32位应用程序可以与32位的DLL和COM组件交互,你的程序应该很需要这个。


根据平台开关,C#编译器会生成一个程序集包含一个PE32或PE32+的表头,编译器会在头文件中声明对于CPU架构的要求(或者无需求)。微软发布了两个命令行工具,DumpBin.exe和CorFlag.exe,你可以用他们检查编译器生成的托管模块生成的头文件信息。


当运行一个可执行文件时,Windows检查这个EXE文件的头文件来确定这个程序需要的是32位或64位的地址空间。一个PE32的头文件可以在32位和64位的地址空间中运行,而PE32+的头文件需要64位的地址空间。Windows也会检查嵌入在头文件中的CPU框架信息确保他和本机的CPU类型符合。最后,64位版本的Windows提供了一个技术允许32位的程序运行。这个技术叫做WoW64(for Windows on Windows64)。




上面的表格表面了两家事。第一,他展示了当你为C#编译器指定不同的 /platform 命令行开关时会生成哪种托管模块。第二,他展示了程序在不同版本的Windows上运行的状况。


在Windows检查了EXE文件的头文件后确定是生成32位或是64位的进程,Windows会在进程的地址空间加载MSCorEE.dll 的x86版或x64版或ARM版。在x86或ARM版本的Windows上,32位版的MSCorEE.dll可以在 %SystemRoot%\System32 目录下找到。在x64版本的Windows上,x86版的MSCorEE.dll 可以在 %SystemRoot%\SysWow64 目录下找到。而64位的MSCorEE.dll可以在 %SystemRoot%\System32 目录下找到(这是为了向后兼容)。然后,进程中的主线程调用MSCorEE.dll 中定义的方法。这个方法初始化CLR,加载EXE程序集,然后调用入口方法(Main)。这样,托管的应用程序就启动运行了。


Note:由1.0或1.1版的C#编译器生成的程序集包含的是PE32头文件而且没有申明CPU框架。However,在加载时,CLR认为这些程序集只是x86的。对于可执行文件,这提升了程序在64位系统上运行的性能因为这个可执行文件会在WoW64加载,给进程一个与32位x86版Windows相似的环境。


注:你的代码可以查询 Environment’s Is64BitOperatingSystem(是否是64位操作系统) 属性来确定代码是否运行在64位版本的Windows。你的代码也可以查询 Environment’s Is64BitProcess (是否是64位进程)属性来确定是否是64位地址空间。


如果一个非托管程序调用 Win32 LoadLibrary 函数来加载一个托管程序集,Windows会加载和初始化CLR(如果还没有加载)以便处理程序集中包含的代码。当然,在这个情况下,经常已经启动并允许了,这有可能限制程序集的可用性。比如,一个由/platform:x86 开关编译的托管程序集完全不能在64位进程中加载,而用同一开关编译的可执行文件可以在64位版本的Windows中的WoW64中运行。

0 0
原创粉丝点击