2012年3月24日星期六

读CLR via C#总结(1) dotNet平台下源代码是如何生成应用程序的

读CLR via C#总结(1) dotNet平台下源代码是如何生成应用程序的



  CLR(Common Language Runtime,公共语言运行时)是.NET Framework框架中最核心的内容,所谓CLR的执行模型,简单地讲就是解释在.NET平台下代码是如何编译和运行的。用一幅图概括如下:

下面是各个阶段的工作。

1,将源代码编译成托管模块

  Microsoft已创建了针对各个语言的编译器,编译时编译器会去分析源代码和检查代码的语法,如果没有问题则能顺利通过编译,最终生成一个托管模块(managed module),托管模块由四部分组成,如下图所示。

  1> PE32文件头:如果使用PE32格式,表明文件在windows的32位和64位版本都能运行,如果使用PE32+格式,表明文件只能在windows的64位版本上运行。PE32文件头标识了文件类型和文件的生成时间。
  2> CLR头:包含了需要的CLR版本,一些标志(flag),托管模块入口方法(Main方法)的MethodDef元数据标记(token)等。
  3> IL代码:即中间语言代码,是编译器编译源代码时生成的代码。在运行时,CLR(JIT编译器)将IL代码编译成本地代码(或称本地CPU指令)。
  4> 元数据:其实就是一个表的集合,一种类型的表描述源代码中定义的类和成员,另一种类型的表描述源代码所引用的类和成员。

2,将托管模块合并成程序集

  CLR实际不和托管模块一起工作,而是和程序集一起工作的。程序集是一个或多个托管模块,以及资源文件(比如图片和html静态页面)的逻辑组合。下图解释了托管模块是如何合并成程序集的。

  注:程序集中有一个清单文件manifest,它是由元数据表构成的表集合,这些表描述了构成程序集的所有文件,以及与程序集关联的资源或数据文件。

3,执行程序集的代码

  要想执行程序集的代码,CLR的JIT编译器首先会把IL代码编译成本地代码。下图解释了JIT编译器是如何把IL代码编译成本地代码然后执行的。

  注:一个方法只有在首次调用时才会进行IL代码验证和编译为本地代码,当第二次调用时不需要再进行IL代码验证和编译,直接执行内存块中的本地代码。但是一旦应用程序终止再次运行应用程序,或者同时启动应用程序的两个实例(使用两个不同的操作系统进程),JIT编译器必须再次进行IL代码验证和编译,因为此时存储在内存中的本地代码已经丢失。



TAG:CLR via C#