[东风哥系列之CLR VIR C#]__CLR执行模型(重口味不喜勿喷)

前车之鉴

       CLR执行模型这部分已经快被博客园网友讲烂了我也就不多讲了,下面给出几个链接:

       点评:这位哥基本上是从书上完全照搬过来的,没有任何自己的见解,见此篇文章如见真书。

       点评:这篇讲得不错,特别是对.Net的规范和实现,看完他的那两张图和下面的说明,你就会明白什么是.Net了。最后说下,这位“菜鸟”哥算得上是一个真正的程序员,广大的程序猿朋友们应该多向他学习!不过可惜,写完这一篇,他后面就没更新了。

       点评:女同志写的,中国教育下的标准版笔记。

A. 什么是.Net

        说起.Net估计谁都不陌生,一般我们口中的.net指的是微软的.net战略,它包含了规范和实现两部分。以下这幅图是根据liudong大哥的图改写的。它或许能让我们更能明白.Net的真正含义。

image

       事实上可以看得出,规范就像一套接口,你想要在那个平台上使用.net就实现该套规范的框架即可。这样做有什么好处呢?没错,就是跨平台,这可是当年微软鼓吹的一个大亮点,不过后来就只见过在windows平台上有.Net,在后来其他平台上的.Net就全让Novell公司给做了(目前流行的Iphone上的MonoTouch,Linux和Android上的Mono)。让你的C#代码可以在少量修改的情况下运行在不同平台上。事实上,这套规范还有一点好处就是混合编程。利用规范定义好的公共类型系统(CTS)和公共语言规范(CLS)开发出的不同语言的编译器,生成出来的IL中间语言代码可以和其他语言生成出的IL中间代码无缝连接。这是规范的两大好处。

      这里说下混合编程。为什么要使用混合编程呢?混合编程是指一个项目使用了多种语言混合编写。假设现在有一个造价项目,其中有一块很复杂的计算使用C#可能会导致效率很低下,这时候使用C++无疑是一个明确的选择,又或者字符串处理模块使用perl可能开发效率会更高些,又或者金融计算使用APL语言会更容易实现,所以.Net提供了这样的功能,让你的项目可支持多种语言混合起来开发,最后每个模块生成规范的IL中间语言。但前提是你使用的语言有基于.Net的编译器。目前支持.Net的语言有:除了常见的C#,C++还有Iron Python、Iron Ruby,Ada,APL,Caml,COBOL,Eiffel,Forth,Fortran,Haskell,Lexico,LISP,LOGO,Lua,Mercury,ML,Mondrian,Oberon,Pascal,Perl,Php,Prolog,RPG,Scheme,Smalltalk 和Tcl/Tk……很遗憾的是,这个特性现在几乎被我们忽略了。

       这也应对了那句话:一流企业卖标准、二流企业卖品牌、三流企业卖产品。不知阁下您的企业是几流呢?

       对于以上涉及到的CLI,CTS,CLS,CIL,CLR,FCL等概念各位看官可以参考这篇文章:

        liudong 菜鸟CLR VIA C#之旅(1):品味细节,CLR的执行模型

       最后盗用用下菜鸟哥的一幅图:

       下面这幅图就很好说明各个概念之间的关系。

image

B. Net程序是如何跑起来的

       先看一个图:

image

       拿个金融项目来说,用C#编写了整个框架,写了N多类,新建了N多文件,VB写了某些界面,也生成了N多文件,Python写了脚本部分,也生成了N多文件,至于多语言混合编程的好处前面已经讲了,那么假设你点了一下‘生成’,系统将会发生什么样的事情呢?首先将你每个文件生成一个托管模块(至于托管模块下面会讲)。

由每个托管模块和你的项目的资源文件例如图片等,将会一起通过连接器(AL.exe,至于连接器,编译器更深入的原理请参考大学计算机课程《编译原理》,这是一门让你非常蛋疼无比的课)一起‘打包’成最终目标文件dll或者exe(至于生成什么类型,可以在项目属性页配置)。这是大概的编译过程。

C. 什么是托管模块

       托管模块这个概念,我一开始经常和程序集混在一起。而死人Jeff老湿经常说:“CLR不和托管模块一起工作,而是和程序集一起工作”。

       鄙人认为:托管模块只是你一个源代码文件通过对应语言编译器生成的另外一个更高层封装的一个文件,里面包含了更多信息(PS:如果你读过原书,那么里面作者还会手把手教你怎么生成一个后缀为.netmodular托管模块的哦亲)。而程序集是由多个托管模块和资源文件构成的一个windows可执行体。

       好吧,不多说先上一个菜鸟哥哥的图:

   image

       上面那幅图说的是:一个托管模块包含了PE32/PE32+头,CLR头,元数据,IL代码。

       下面是作者对于这四个概念的叙述:

image

       关于元数据再说明一点,平时我们敲代码,打个X,可以出个XXXXXO这种智能感应,通过的就是你编译后的元数据来识别,元数据就相当于以前C++头文件的升级版,他提取了你源代码文件中所有的公开属性,公开方法和接口等。这种做法的方便之处就不多解释,智能感应只是其中一种。

D. 隐藏章节:IL与反编译

      说起IL,让我不仅想起了老赵的:

      老赵谈IL(1):IL是什么,它又不是什么?那么汇编呢?

      老赵谈IL(2):CLR内部有太多太多IL看不到的东西,包括您平时必须了解的那些

      老赵谈IL(3):IL可以看到的东西,其实大都也可以用C#来发现

      对于IL,我就不多讲了,讲了会被老赵喷的。

      其实CLR类似于一个操作系统,只不过它是运行在Windows上,那么CLR也有统一的汇编语言就是IL。而且我们口中的编译器:就是把你编写的源代码,统一转化成CLR所认识的IL语言,这其实也体现了一个高度封装的过程。对于这个编译过程:这其中也发生了很多不为人知的转化(既然不为人知,那么我也是不知道的),比如去掉注释,优化代码。

      国际惯例,来个Helloworld:

      为了获得编译后的IL,我们必须借助一个反编译神器Reflector,估计地球人都知道(亲,如果你还不知道或者苦于找不到破解版,请猛击这里Reflector7.3带插件破解版)。

       image

       这是它的界面,只要把exe或者dll往里面拖即可,即拖即用。

 image

    至于IL代码,就不多做解释了,有兴趣的童鞋可以查阅相关资料或者看原书作者讲解。

     再来看下反编译之后的C#代码:image在下拉中选择C#即可。

private static void Main(string[] args)
{
    Console.WriteLine("Helloworld!");
}

      可以看到反编译出来的结果竟然是没有了i的定义和赋值。但事实上,在IL代码中,这部分代码还是存在的。例如:L-0003:ldc,i4,3    这一句是i的赋值语句,所以千万别误会成在生成IL的时候,编译器自动优化掉了(估计是Reflector反编译IL代码时给优化掉了,还望知道的大神讲解?)。

      这时候估计有些童鞋会说了:啊?幸幸苦苦做出来的软件,代码却被Reflector霸王硬上弓了。要是在根据源代码重新编写一个接口一样,但实现中加入恶意代码的dll替代原来的dll分发出去,那后面大家都懂的… …。

       各种谜团,各种防范技巧,敬请期待下一章:弱命名程序集与强命名程序集。

       最后小小说明一下:本系列课程原是我在公司每天下班前的30分钟培训内容,所以同时也附上PPT:CLR VIR C#[1]__执行模型

      

posted on 2012-07-16 23:49  kingmoon  阅读(3125)  评论(6编辑  收藏  举报

导航