CLR via C#:CLR执行模型

基础知识点:如下所示:
1.Windows的CPU架构类型主要分为32位的x86以及ARM和64位的x64。
2.x64 Windows通过WoW64技术运行x86 Windows应用程序。
3.PE32表示32位可移植执行体文件;PE32+表示64位可移植执行体文件。
4.如果机器上含有MSCorEE.dll库文件的话,就表明机器上安装了.Net Framework。其中Windows为x86,x64以及ARM的MSCorEE.dll文件存放在%SystemRoot%/System32目录下;而使用WoW64技术的MSCorEE.dll文件存放在%SystemRoot%/Wow64目录下。
5.32位Windows的.Net Framework版本存放在%SystemRoot%/Microsoft.NET/Framework目录下;64位Windows的.Net Framework版本存放在%SystemRoot%/Microsoft.NET/Framework64目录下。
6.程序集是占用一个单独的进程,每个程序集之间互相独立运行。

CLS,CTS,CLR之间的关系:如下所示:
1.CLS也叫做公共语言规范,用来定义编译器支持的最小功能子集。在C#中可以使用[assembly:CLSCompliant(true)]特性来告诉编译器检查程序集中任何public类型是否在其他编程语言中可以正常访问。
2.CTS也叫做公共类型系统,用来描述类型的定义和行为。具有以下特性:
1>.指定类型可以拥有0或者多个成员。如:方法,属性(get,set),字段和事件。
2>.指定类型的可见性规则和类型中成员的访问规则。如:public,private等。
3>.指定类型继承,虚方法,对象生存周期的规则。
4>.指定所有类型必须从System.Object类型继承。
3.CLR也叫做公共语言运行时,只要编程语言(C#,Lua,IL汇编等)是面向CLR规范的,那么这些编程语言也就具有CLR中定义的部分或者全部能力(内存管理,程序及加载,安全性,异常处理和线程同步等)。
4.CLR/CTS提供了一个功能集;不同的编程语言(C#,Lua,IL汇编等)提供了CLR/CTS的部分或者全部功能实现,而这些编程语言都会提供CLS提供功能的全部实现。如图所示:
在这里插入图片描述
托管执行过程:如下所示:
1.使用C#编写源代码文件。
2.使用C#编译器将C#源代码文件编译成托管模块。
1>.编译器主要做语法检查以及分析源代码工作。
2>.托管模块主要是由中间语言(也称托管代码,是一种面向对象的机器语言,最终被CLR加载执行)以及元数据(描述托管模块中定义了什么以及引用了什么)组成。
3.使用AL.exe(程序集链接器)将托管模块和资源文件合并到一个程序集中。
4.执行程序集代码。流程如下:
1>.检查EXE文件头决定是创建32还是64位进程并在进程地址空间加载MSCorEE.dll。
2>.初始化CLR并加载EXE程序集。
3>.将程序集中引用的类型以及该类型定义的所有函数存储在一个Type表中进行管理。
4>.调用主入口函数Main。当首次调用某类型中的某函数时就会调用JITCompiler函数编译成机器码并执行,往后再次调用该函数时就直接调用编译后的机器码进行执行。其中JITCompiler函数执行过程如下所示:
1>>.在负责实现类型的程序集的元数据中查找被调用的方法。
2>>.从元数据中获取该方法的IL。
3>>.分配内存块。
4>>.将IL代码编译成机器码并存储在3>>步骤分配的内存块中。
5>>.在Type表中修改与方法对应的条目,使它指向3>>步骤分配的内存块,从而第二次调用时可以直接执行机器码。
6>>.跳转到3>>步骤中分配的内存块并执行机器码。

C#编译器开关详解:如下所示:
1./platform开关选项对生成的托管模块以及运行时的影响如下表所示:

/platform开关 生成的托管模块 x86 Windows x64 Windows ARM Windows RT
anycpu(默认) PE32 作为32位应用程序运行 作为64位应用程序运行 作为32位应用程序运行
anycpu32bitpreferred PE32 作为32位应用程序运行 作为WoW64应用程序运行 作为32位应用程序运行
x86 PE32 作为32位应用程序运行 作为WoW64应用程序运行 不运行
x64 PE32+ 不运行 作为64位应用程序运行 不运行
ARM PE32 不运行 不运行 作为32位应用程序运行

2./optimize和/debug开关选项分别对生成的IL代码质量以及JIT代码质量的影响如下表所示:

编译器开关设置 IL代码质量 JIT代码质量
/optimize- /debug-(默认) 未优化 有优化
/optimize- /debug(+/full/pdbonly) 未优化 未优化
/optimize+ /debug(-/+/full/pdbonly) 有优化 有优化

3./unsafe开关是C#编译器用来编译具有unsafe关键字的C#源码。当CLR的JIT编译器用来编译程序集中的unsafe方法时就会检测程序集是否被授予了System.Security.Permissions.SecurityPermission权限以及System.Security.Permissions.SecurityPermissionFlag的SkipVerification是否设置,如果没有就会报错并终止执行。

微软提供的常用工具:如下所示:
1.CLRVer.exe工具用来来查看.Net Framework的版本信息。
2.AL.exe工具用来将托管模块和资源文件合并到一个程序集中。
3.DumpBin.exe以及CorFlags.exe工具用来查看托管模块所嵌入的信息。
4.PEVerify.exe工具用来检查程序集中所有的方法并报告出含有不安全代码的方法。
5.NGen.exe工具用来在安装应用程序时将所有IL代码预编译成机器码并存储在磁盘上(位于%SystemRoot%/Assembly/NativeImages_v4.0.#####_64目录下,其中v4.0表示CLR版本号,64表示Windows系统位数)。具有以下特点:
1>.当执行应用程序时CLR会检测应用程序是否有被预编译,如果有就直接执行预编译的机器码,从而提高应用程序的启动速度。
2>.当应用程序被加载到多个进程中时,由于预编译的机器码只有一份且会链接到不同的进程中,从而减小应用程序工作集的大小。
3>.CLR加载NGen.exe生成的机器码时,会和当前执行环境(CLR版本,CPU类型,Windows系统版本,安全性,引用的程序集版本ID,程序集的模块ID等)进行比较,如果不匹配的话,就会将程序集中的IL使用JIT进行编译成机器码,此时就没有知识产权保护以及NGen.exe生成的机器码失去同步。
4>.NGen.exe的编译策略相比JIT编译策略来说比较保守,生成的机器码没有进行高度优化,所以在执行时性能较差。
6.MPGO.exe工具用来分析程序执行,检测启动时需要哪些东西,并把这些信息提供给NGen.exe,从而方便NGen.exe更好的预编译机器码。

发布了81 篇原创文章 · 获赞 39 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/zjz520yy/article/details/103718680