C#CLR via C#读书笔记一:CLR的施行模型

 

CLR(Common Language
Runtime)
集体语言举办时是一个可由多种编程语言使用的“举办时”。

  • 将源代码编译成托管模块

可用匡助CLR的其他语言创制源代码文件,然后用相应的编译器检查语法和分析源代码。无论采纳哪个编译器,结果都是托管模块(managed
module)。
托管模块是业内的32位Microsoft
Windows可移植执行体(PE32)文件,或者是正规的64位Windows可移植执行体(PE32+)文件,他们都急需CLR才能执行。(注:PE是Portable
Executable(可移植执行体)的简称)

C# 1C# 2

本机代码编译器(native code
compilers)生成的是面向特定CPU架构(比如x86,x64或ARM)的代码。相反,每个面向CLR的编译器生成的都是IL(中间需要)的代码。

   除了生成IL面向CLR的编译器还要在各样托管模块中生成完全的元数据(metadata)。元数据简单地说就是一个数据表集合。一些数据表描述了模块中定义了怎么(比如类型及其成员),另一些描述了模块引用了何等(比如导入的类别及成员)。

  Microsoft的C++编译器默认生成包含非托管(native)代码的exe/dll模块,并在运转时操作非托管数据(native内存)CLR即可执行。不过,通过指定/CLR命令行开关,C++编译器就能生成包含托管代码的模块。当然,最后用户必须安装CLR才能履行这种代码。在头里提到的持有Microsoft编译器中,C++编译器是惟一的,唯有它才允许开发人士同时写托管和非托管代码,并扭转到同一个模块中。它也是唯一允许开发人员在源代码中同时定义托管和非托管数据类型的Microsoft编译器。

  • 将托管模块合并成程序集

  CLR实际不和模块工作。它和程序集工作。

  首先,程序集是一个或四个模块/资源文件的逻辑分组。其次,程序集是重用、安全性以及版本控制的矮小单元。

  C# 3

  图中有些托管模块和资源(或数量)文件准备交由一个工具处理。工具生成代表文件逻辑分组的一个PE32(+)文件。实际爆发的政工是,这些PE32(+)文件包含一个名为清单(mainfest)的数据块。清单也是元数据表的聚众。这几个表描述了咬合程序集的文本、程序集中的公文所实现的当众导出的门类以及与程序集关联的资源或数据文件。(注:所谓公开导出的品种,就是先后集中定义的public类型,它们在程序集内部外部均可见。)

   编译器默认将转移的托管模块转换成程序集。也就是说,C#编译器生成的是带有清单的托管模块。清单提出程序集吸由一个文书构成。对于只有一个托管模块而且无资源(或数量)文件的类型,程序集就是托管模块,生成过程中无需实践此外附加的步骤。然而,假如期待将一组文件合并到程序集中,就亟须撑握更多的工具(比如程序集链接器AL.exe)及其命令行选项。

  • 加载公共语言运行时CLR

  可执行文件(exe)运行时,Windows检查EXE文件头,决定是创办32位仍旧64位过程之后,会在过程地址空间加载MSCorEE.dll的x86,x64或ARM版本。要是是Windows的x86或ARM版本,MSCorEE.dll的x86版本在%SystemRoot%\System32目录中。如果是Windows的x64版本,MSCorEE.dll的x86版本在%SystemRoot%\SysWow64目录中,64位版本则在%SystemRoot%\System32目录中(为了向后分外)。然后,进程的主线程序调用MSCorEE.dll中定义的一个主意。这一个艺术初阶化CLR,加载EXE程序集,再调用其进口方法(Main)。随即,托管应用程序启动并运行。(PS:微软在64位系统大校所有拍卖32位程序的工具都置身SysWow64目录下,Wow就是Windows
on
Windows的情致。而System32索引是处理64位程序的。还叫32,只是延续了以前的叫法,其实应当是64)

  • 履行顺序集的代码  

  开发人士一般用c#,VB等高档语言举行编程。它们的编译器将生成IL。但是,和任何任何机器语言一样,IL也能选拔汇编语言编写,Microsoft甚至专门提供了名为ILAsm.exe的IL汇编器和名为ILDasm.exe的IL反汇编器。注意,高级语言平常只公开了CLR全体效用的一个子集。然则IL汇编语言允许开发人士访问CLR的方方面面效率。要精晓CLR具体提供了怎么职能,唯一的点子是读书CLR文档。

  为了施行格局,首先必须把艺术的IL转换成本机(navive)CPU指令。这是CLR的JIT(just-in-time或者”即时”)编译器的天职。

C# 4

就在Main方法执行在此以前,CLR会检测出Main的代码引用的所有品种。这导致CLR分配一个里面数据结构来保管对引用类型的拜访。图中Main方法引用了一个Console类型,导致CLR分配一个内部结构。在这多少个里面数据结构中,Console类型定义的各样方法都有一个对应的笔录项。每个记录项都富含一个地址。遵照此地方即可找到方法的兑现。对那些结构起初化,CLR将每个记录项都设置成(指向)包含在CLR内部的一个未编档函数。我将该函数称为JITCompiler。

Main方法第一次调用WriteLine时,JITCompiler函数会被调用。JITCompiler函数负责将艺术的IL代码编译成本机CPU指令。由于IL是”即时“(just
in time)编译的,所以一般将CLR的这一个组件称为JITter或者JIT编译器。

JITCompiler函数被调用时,它知道是要调用的是哪些方法,以及具体是什么类型定义了该措施。然后,JITCompiler会在概念(该项目标)程序集的元数据中摸索被调用方法的IL。接着JITCompiler验证IL代码,并将IL代码编译成本机CPU指令。CPU指令保存到动态分配的内在块中。然后
,JITCompiler回到CLR为项目创立的里边数据结构,找到与被调用方法对应的这条记下,修改最初对JITCompiler的引用,使其针对性内在块(其中涵盖了刚刚编译好的本机CPU指令)的地点。最后,JITCompiler函数中跳转到内存块中的代码。这个代码正是WriteLine方法(获取单个String参数的相当版本)的切实可行落实。代码执行完毕并回到时,会回来Main中的代码,并像以往同一继续执行。

前些天,Main要第二次调用WriteLine。这几遍,由于已对WriteLine的代码举办了求证和编译,所以会一贯实施内存块中的代码,完全跳过JITCompiler函数。WriteLine方法执行完毕后,会重复重临Main。

  •  IL和验证

  将IL编译成本机CPU指令时,CLR执行一个名为证实(verification)的经过。

  CLR确实提供了在一个操作系统中履行之个托管应用程序的能力。每个托管应用程序都在一个AppDomain中施行。每个托管EXE文件默认都在它自己的独门地址空间中运行,这么些地点空间只有一个AppDomain。但是,CLR的宿主进程(比如IIS或者Microsoft
SQL Server)可决定在一个进程中运作四个AppDomain。

  • 本机代码生成器:NGen.exe

  采用用.NET
Framework提供的NGen.exe工具,可以在应用程序安装到用户的处理器上时,将IL代码编译成本机代码。由于代码在装置时曾经编译好,所以CLR的JIT编译器不需要在运作时编译IL代码,这有助于提升应用程序的特性。NGen.exe能在偏下二种状态下发布关键功能。

  1提升应用程序的启动速度

  2收缩应用程序的干活集(所谓工作集,是指在过程的拥有内存中,已映射的情理内存这有些(即这多少个内存全在物理内存中,CPU可以直接访问);进程还有一对虚拟内存,它们可能在更换列表中(CPU无法通过虚拟地址访问,需要Windows映射之后才能访问);还有局部内设有磁盘上的分页文件里。)

  NGen.exe生成的文件有以下问题

  1没有文化产权珍爱

  2NGen生成的文本或者错过同步

  3较差的施行时性能

  • Framework类库

  FCL(Framework Class
Library)

  • 通用项目系统

  Microsoft制定了一个正式规范来讲述类型的概念和作为,这就是“通用项目系统”(Common
Type System,CTS)。

  • 公共语言专业

  要创造很容易从此外编程语言中做客的品类,只好从友好
的语言中挑选其他所有语言都辅助的效用。为了在这一个地方提供匡助,Microsoft定义了“公共语言专业”(Common
Language
Specification,CLS
),它详细定义了一个微小效率集。任何编译器只有匡助这么些效率集,生成的连串才能匹配由其余符合CLS、面向CLR的言语生成组件。
  (个人的精晓:CLS是为着不同编程语言之间相互调用而规划的,倘诺只用一种语言,就不要考虑CLS的规范)

  (说明:文中99%内容来自书本原文。把文化要点搬运到这边,只是为了方便我复习、查阅)

相关文章