CLR vir C# 之CLR执行模型

     从今天开始读CLR vir C#.虽然是英文版,但希望能从刚刚读完的《你必须知道的.net》中找到共鸣。

 

     本文简单阐述从Source Code 到CPU Native Code 的执行期间,发生了什么事?    

 把源码编译成托管代码

      在.net环境下,我们可以采用多种语言来进行编程,比如C#,Vb.net,J#等。并且多种语言可以同时存在于同一专案中,这涉及到了CTS的内容,暂不阐述。每种语言都有其对应的编译器存在,C#->CS Compiler,Vb.net->Basic Compiler等。如下图

 

     

 

     不管什么语言,通过各自的编译器编译后,都会生成PE文件(Portable Executable file)也即托管模块(Managed Module).通常托管模块包括以下几部分:
     1.PE(32) Header

     2.CLR Header (两者描述一些附加信息)

     3.MetaData  (主要包括两个原数据表:一个描述源码中的类型和成员信息,一个面熟源码引用到的类型和成员信息)

     4.IL(中间代码:不管哪种编程语言(net支持的),都要编译为统一的中间代码)

     注意:元数据在这里是个很重要的角色,由于它的“自我描述”(由两个原数据表决定了)简单的来说,它可以:

     1)造就了net的智能感知

     2)允许对象的字段被序列化与反序列化(*)

     3)使得GC可以追踪到对象的引用关系,得到对象的生命周期

     4)保证了编写安全的代码(*)

 

     托管模块生成Assembly

     到达中间代码,接下来好像就轮到CLR 的JIT编译机制,在运行时把其编译成本地代码即可。实际上,CLR是不与managed module发生作用的,managed module要首先由对应的编译器编译成Assembly(DLL, exe)后,CLR与Assembly交互。见下图:
     

 

     根据我们平时的编程经验来理解上述Assembly生成:比如一个winform专案,里面包括form ,images等资源,编译时,可以选择生成类库(DLL),或者可执行文件(EXE),这个时候,就会把所有的资源(源码,images)等全部“打包”成一个DLL/Exe,如果是建立类库的专案则更加如此。

     当然,生成的Assembly(DLL/Exe)要想在客户端运行,需要CLR的支持,这也就是为什么我们在部署的winform专案的时候,在client端安装framework的原因了。

     JIT执行Assembly

     从上面的描述中可以知道,生成的Assembly是在运行时由JIT进行编译执行的,而这个过程正式托管程式性能的一个很到的体现:

     如下代码:
     

Code

     当第一次调用WriteLine方法时,

     1.JIT Compiler从元数据中找到要调用的方法,

     2.从而找到方法在IL中的位置,这个动作可以从上面对元数据的描述中得到得以解释。

     3.分配空间

     4.JIT把IL编译成本地代码

           (注:这个过程中实际上还有一个动作:Verification(验证),此验证用来保证代码的安全性。比如验证方法参数是否一致,返回值是否正常返回等。)

     5.把生成的本地代码存储在动态生成的内存空间中

     6.运行指针跳转至本地代码执行

     这个过程简单的阐述了运行时的JIT工作流程。

     当第二次调用WriteLine方法时,由于在本地内存中已经存储有此方法的本地代码,所以JIT的编译过程将被绕过,直接执行本地代码,从而使执行性能得到提高。

     从这个角度看,我们平时讲的封装和复用等思想,在代码优化,性能提高方法都会起到很好的作用。

     当然,如果应用程序关闭,动态内存得以释放,生成的本地代码也就不存在了。

 

      CTS通用类型系统

     上文中提到,net实现了多语言的互操作,这个特性需要CTS和CLS的支持。

     CTS中定义类型中能够定义什么,如何定义等规范,并对类型的访问级别做了规范(private,famlily,public等),可以看到,里面的定义如family实际上对应的IL中的定义,具体的每种语言中都有自己的映射定义,如protected.

     又比如对数据类型的定义,CTS中的Int32,在C#中可以为int即可。这些只是

一些映射定义,编译为IL后,实际还是要称为CTS中定义的类型Int32.

     这种特性,就使得开发者可以用自己熟悉的语言,自己熟悉的语法进行编程,完成后还可以进行与其他语言代码的交互。

     而相反,没有在CTS中定义的规范,在具体的语言中是不可用的:比如C++语言支持多继承,而在CTS中定义对于类只是是单向单继承,所以net环境下写C++代码就必须符合这个规范,写多继承的代码会出现编译错误。

     CLS通用语法规范

     如果说CTS定义了统一的编程规范,那么CLS就定义了实现语言互操作每种语言必须符合的最小集合。

     如果要实现互操作的编码,可以使用[assembly:CLSCompliant(true)] 特性,来检查代码是否符合CLS规范。

Code

     由于在VB.net中不存在Uint32的定义,所以foo方法会得到警告:不符合CLS规范。

     具体的规范内容,需要参考相关文档得知。

 

posted on 2008-08-20 14:18  easy2Dev  阅读(726)  评论(1编辑  收藏  举报

导航