CLR基础小结

时至今日,CLR基础部分的学习算是告一段落了。可是由于知识有些庞杂,因此但愿在此处作一些总结,以整理所学所得。html

1.CLR的执行模型:编程

简单来讲,这部分所叙述的,就是如何将源代码生为一个应用程序,或者生成为一组能够从新分发的组件,以及这些组件中包含的类型。最后还解释了应用程序如何执行。数组

源代码编译成托管模块安全

首先,必需要了解的一个事情就是,CLR的核心功能,以及CLR在托管的时候所作的事情。CLR,全称Common Language Runtime,公共语言运行时,是一个可由多种编程语言使用的“运行时”。任何面相CLR的语言均可以使用CLR的核心功能。使用支持CLR的语言建立了源代码文件,而后用对应的编译器检查语法和分析源代码。不管是选择哪一个编译器,都是生成托管模块(好比C#就是:C#源码经过C#编译器生成了托管模块)。所谓托管模块,就是可移植执行体文件(.exe,.dll,.scr等都是可移植执行体文件)。数据结构

本机代码编译器(native code compilers)生成的是面相CPU架构的代码。而每一个面相CLR的编译器生成的都是IL(Intermediate Language,中间语言)代码。IL代码也被称为托管代码,由CLR管理它的执行。除了生成IL,面相CLR的每一个编译器还要在每一个托管模块中生成完整的元数据。元数据是一个数据表的集合,描述了数据的各类引用、定义等。编译器会同时生成元数据和IL代码,将之绑在一块儿,嵌入进最终生成的托管模块,因此元数据和它描述的IL代码一直是同步的。架构

编译器生成的数据,分为托管模块(包含托管代码IL和托管数据集的模块),和非托管模块(不须要CLR执行, 在运行时直接操纵非托管数据)。app

托管模块合并成程序集编程语言

托管模块并非CLR的工做对象,而程序集(assembly)才是。程序集,是一个或多个模块/资源文件的逻辑性分组,也是重用、安全性以及版本控制的最小单元。多个托管模块和资源文件,经过一些合并程序集所用到的工具,例如C#编译器(CSC.exe),合并成了程序集(托管模块合并成了IL和元数据,资源文件仍是资源文件)。函数

加载CLR工具

生成的程序集,能够是.exe、.dll,最终由CLR管理这些程序集中代码的执行。换言之,机器必须安装好.NET Framework。在可执行文件运行时,Windows检查文件头(32位or64位);而后检查头中嵌入的CPU架构信息。在肯定CPU符合要求后,运行该程序。

为了运行托管应用程序,Windows检查EXE文件头,建立好进程后,会在进程地址空间加载MSCorEE.dll的x86,x64或ARM版本。而后,进程的主线程调用MSCorEE.dll中定义的一个方法。这个方法初始化CLR,加载EXE程序集,再调用入口函数main。

若是是非托管,则应用程序调用LoadLibrary加载托管程序集,Windows会自动加载而且初始化CLR以处理程序集中的代码。

执行程序集代码

托管程序集同时包含元数据和IL。IL能访问操做对象类型,并提供了指令来初始化对象、调用对象上的虚方法以及直接操做数组元素,甚至能够抛出异常。能够把IL当作一种面向对象的机器语言。

为了执行方法,首先必须把IL转换成本季CPU指令,这是CLR的JIT编译器的职责。在Main执行以前,CLR会检测出Main的代码所引用的全部类型。此时,CLR会分配一个内部数据结构来管理对引用类型的访问。在这个内部结构中,每一个类型的每一个方法都有一个对应的记录项(entry,也能够翻译成入口),每一个记录项都有一个地址,根据这个地址能够找到对应方法的实现。对这个结构初始化的时候,CLR将每一个记录下都设置成包含在CLR内部的一个未编档函数,也就是JITCompiler。

Main首次调用函数的时候,JITCompiler被调用。JITCompiler负责将方法的IL代码编译成本机指令。由于IL是JIT(just-in-time,即时)编译的,因此把CLR的这个组件称为JIT编译器。JITCompiler的执行过程以下:

●在负责实现类型的程序集的元数据中查找被调用的方法

●从元数据中获取该方法的IL

●分配内存

●将IL编译成本机CPU指令,而后将这些本机代码存储到分配的内存中

●在Type表中修改与方法对应的条目,使其指向分配的内存块

●跳转到内存块中的本机代码

在Main第二次调用的时候,由于已经对方法进行了验证和编译,因此会跳过JITCompiler直接执行内存块的代码。也正因如此,才使得仅在首次调用的时候才会发生性能损失。

将IL编译成本机CPU指令的时候,有一个验证的过程。这个过程会检查IL代码,肯定代码的安全性。

Microsoft C#编译器默认生成安全的代码,可是也容许开发人员写不安全的代码。所谓不安全的代码,就是代码能够直接操做内存地址。使用的时候,不安全代码的方法须要用unsafe作标记。而且在编译的时候,须要使用/unsafe开关来编译源代码。

NGen.exe

NGen.exe工具,能够在应用程序安装到用户的计算机上时,将IL代码编译成本机代码。由于代码在安装的时候已经编译好,因此一般不须要在运行的时候编译IL代码。因此,NGen.exe的主要做用是:提升应用程序的启动速度,以及减小应用程序的工做集。

每当CLR加载程序集文件,都会检查是否存在一个对应的、由NGen生成的本机文件。若是找不到本机文件,CLR就和往常同样对IL代码进行JIT编译。若是有对应的本机文件,CLR就直接使用本机文件中编译好的代码,不须要在运行时编译。

可是,NGen生成的文件也会有以下问题:没有知识产权保护、生成的文件可能丢失同步、较差的执行性能。因此,服务端的应用程序,NGen的做用就不甚明显。而在客户端的程序,就能够提升启动速度、缩小工做集等。

本章的其余内容为后续章节的概述,不涉及很复杂的理解,因此就不在此作过多赘述了。


2.生成、打包、部署和管理应用程序及类型:

在本章,将重点解释如何生成仅供本身的应用程序使用的程序集

将类型生成到模块中

Program.cs

 1 using System;
 2 
 3 namespace Project_1
 4 {
 5     public class Program
 6     {
 7         public static void Main(string[] args)
 8         {
 9             System.Console.WriteLine("HaHa");
10        }
11     }
12 }

执行命令,生成可执行文件Program.exe:csc.exe /out:Program.exe /t:exe /r:MscorLib.dll Program.cs

能够简化为:csc.exe Program.cs

响应文件,是包含一组编译器命令行开关的文本文件。执行CSC.exe时,编译器打开响应文件,并使用其中包含的全部开关。此外,编译器还会查找CSC.rsp文件。该文件引用了和CSC.exe相关的全部程序集。

元数据

元数据是由三种表构成的二进制数据块:定义表,引用表和清单表。编译源码的时候,任何定义的东西都致使在某个表中建立一个记录项。此外,编译器还会检测源码引用的类型、字段、方法、属性和事件,并建立相应的元数据表记录项。在建立的元数据表中包含一组引用表,包含了引用的内容。

要查看元数据表,可使用IL反汇编工具ILDasm.exe:ILDasm Program.exe

将模块合并成程序集

 这部份内容涉及到不少实际操做,具体内容就不作赘述了,详情请见https://www.cnblogs.com/renzhoushan/p/10366289.html。这里只简述一下为何这样作。

之因此要引入“程序集”的概念,就是为了可重用类型的逻辑表示与物理表示能够分开。之因此使用多文件程序集,主要用以下三点理由:

●不一样类型用不一样的文件,使得文件能够以“增量”方式下载;

●能够在程序集中添加资源或数据文件;

●程序集包含的各个类型能够用不一样的编程语言来实现。

程序集版本资源信息和语言文化

 在生成PE文件程序集时,还会在PE文件中嵌入标准的Win32版本资源,能够查看文件属性来检查该资源的版本号。

 除了版本号,程序集还将语言文化做为身份标识的一部分。若是程序包含语言文化特有的资源,Microsoft会建议专门建立一个程序集来包含代码和应用程序的默认资源。生成该程序集时不要指定具体的语言文化。其余程序集经过引用该程序及来操纵它公开的类型。而后,建立一个或多个单独的程序集,只在其中包含语言文化特有的资源:不包含任何代码。标记了语言文化的程序集,被称为附属程序集。为附属程序集指定的语言文化应准确反映程序集中的资源的语言文化。想要支持的每种语言文化都要建立单独的附属程序集。

简单的应用程序部署:私有部署的程序集

 不一样的程序集打包方式不一样。例如,Windows Store应用在打包的时候,VS会将全部必要的程序集打包成一个.appx文件。用户在安装的时候,其中包含的全部程序集都进入一个目录,CLR从该目录加载程序集,Windows则在用户的“开始”添加对应的程序磁贴。若是是其余用户安装一样的.appx,则会使用以前安装好的,只是添加了一个磁贴。在卸载的时候,也是先删除磁贴。若是没有其余用户安装该应用,就删除目录和其中全部的程序集。

在应用程序基目录或者子目录部署的程序集称为私有部署的程序集,这是由于程序集文件不和其余任何程序共享。之因此能实现简单的安装/移动/卸载,是由于每一个程序及都用元数据注明了本身引用的程序集,不须要注册表设置。

简单管理控制/配置 

 为了实现对应用程序的管理控制,能够在应用程序目录放入一个配置文件。发布者能够建立并打包该文件。安装程序会将配置文件安装到应用程序的基目录。此外,计算机管理员或最终用户也能建立或修改该文件,CLR会解析文件内容来更改程序集文件的定位和加载策略。

3.共享程序集和强命名程序集:

相关文章
相关标签/搜索