好吧,废话少说,先上一章Hello World图:

我们有了一个Hello world程序,如此之简单,再加上我今天没有用汉字编程o(>﹏<)o,所以一切很简单明了。

故事开始:

编译:

一个程序写完肯定要编译,以前什么C啊什么的都是编译成本机的CPU指令,但是我们的C#不是。

C#,VB.NET都会把它们编译成托管模块,托管模块在一个标准的可移植的PE文件中。(那些懵懂的少年肯定慌了,这是什么鬼,又是托管模块又是PE文件的。莫慌,所有你听不懂的高大上的术语其实都很简单,你现在不需要懂,听我慢慢道来)

所谓PE文件,就是可移植执行体,简单来讲就是.EXE和.DLL这种鬼东西(这个exe和C语言生成的有区别的)。这个PE文件里的托管模块,你可以当做一个对象,对象里有四个属性,一个PE头(描述文件),一个CLR头(描述这个对象的整体的一些信息,比如main入口),元数据(这个很关键,一种元数据表包含源代码中定义的那些那些类型和成员的描述信息,另一种包含引用的类型和成员的描述信息),IL代码(就是你的源代码被编译后的代码,又称中间语言)。

如果觉得麻烦,前面两个属性你可以忘掉了,记住后面两个就好:元数据和IL代码(简单来讲,就是代码的描述信息和编译后的代码)。

但是一个PE文件可不只一个托管模块,它可以由几个托管模块组成。编译器会把多个托管模块和资源文件合并成一个包含清单的程序集,这才是最后的PE文件。

运行:

但是这个托管模块也就是PE文件并不能直接运行,他需要CLR。

CLR常用简写词语,CLR是公共语言运行库(Common Language Runtime)和Java虚拟机一样也是一个运行时环境,它负责资源管理(内存分配和垃圾收集等),并保证应用和底层操作系统之间必要的分离。CLR存在两种不同的翻译名称:公共语言运行库和公共语言运行时。

此描述及以后的描述均来自百度百科,我懒得手打。

CLR的核心功能包括:内存管理,程序集加载,安全性,异常处理和线程同步。

这个东西又称为公共语言运行时。

前面的说到不能直接运行的时候,这里有懵懂的少年肯定说,我生成的exe文件明明可以直接运行。

这是因为你的电脑上安装了.NET Framework。当你在打开exe程序的时候你的进程的主线程会调用MSCorEE.dll的一个方法,这个方法会初始化CLR,再加载exe程序集,然后调用入口方法即main函数。

所以说实际上你的代码运行是需要在CLR上的。

那么CLR到底是怎么玩我们的Hello world的?

它会在运行时编译我们的IL代码。(先别吐槽为什么要编译两次,后面有讲)

早在Main函数执行之前,CLR就会检测Main的代码所引用的所有类型,然后生成了一个内部的数据结构来管理引用类型的访问。

在这个内部结构中,每个类型比如Console的每个方法都会有一个入口,每个入口都有一个地址(这里叫地址A吧),这个地址A就可以找到方法的实现代码。

而在这个内部数据结构初始化的时候,所有的这些入口的地址都会被设置成一个叫JITCompiler的函数。

就比如上面图中的hello world代码第一句,CLR在执行这句代码的时候会跑进JITCompiler这个函数中,这是内部操作:

  1. 会跑进托管模块,然后根据元数据匹配类名和方法名,获取你要执行的Console这个类里面Writeline这个函数在IL代码里面的地址B。
  2. 然后编译这段IL代码变成本机的CPU指令放到一块内存空间中,地址为C。(在这个编译之前还会进行验证哦,验证这个IL代码是否安全)
  3. 接着修改元数据中地址A的值变为地址C的值。
  4. 最后跳转到地址C开始执行地址C的cpu指令。

那么如果我们第二次去执行Writeline函数呢?此时内部结构中Writeline函数入口的地址指向的已经是编译好的CPU指令的地址了,所以也就不会去执行JITCompiler这个函数。

千万不要认为这样一定会很慢哦,除了第一次运行时JITCompiler的编译可能需要花费掉编译和优化的时间,后来执行的就是本地CPU指令哦。再加上JITCompiler的这个编译会根据你的机器的CPU不同可能会去生成一些专属于本CPU的特殊指令去优化IL代码,有的这种托管程序可能还要比非托管程序快。

好了,本章的精髓就是上面这些了。

现在我们想想为什么要编译两次?

因为这样的话,无论用C#、VB、F#这些东西你都可以生成一样的包含IL代码的托管程序集,然后这个托管程序集在CLR上运行,也就是说可以混合写代码,一个C#代码可以调用VB代码的DLL,用最适合的语言做最适合的事情。

并且在CLR监视之下执行的IL代码因为在执行前会进行安全校验,所以会提高程序的健壮性和可靠性。

【C#进阶系列】01 CLR的执行模型——一个Hello World的故事的更多相关文章

  1. 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型

    .Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...

  2. 01.CLR的执行模型

    在非托管的C/C++中,可以进行一些底层的操作     "公共语言运行时"(CLR)是一个可由多种编程语言使用的"运行时"          CLR的核心功能包 ...

  3. C#进阶系列 ---- 《CLR via C#》

      [C#进阶系列]30 学习总结 [C#进阶系列]29 混合线程同步构造 [C#进阶系列]28 基元线程同步构造 [C#进阶系列]27 I/O限制的异步操作 [C#进阶系列]26 计算限制的异步操作 ...

  4. JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

    本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 ■ 跨浏览器事件处理 □ 事件必须在页面元素加 ...

  5. JavaScript进阶系列01,函数的声明,函数参数,函数闭包

    本篇主要体验JavaScript函数的声明.函数参数以及函数闭包. □ 函数的声明 ※ 声明全局函数 通常这样声明函数: function doSth() { alert("可以在任何时候调 ...

  6. CLR 的执行模型(2)

    第一章 CLR 的执行模型(2) 本篇内容大纲 Framework 类库(Framework Class Library , FCL) 通用类型系统(Common Type System,CTS) 公 ...

  7. 第一章 CLR 的执行模型

    CLR via C# 读书笔记:第一章 CLR 的执行模型(1) 第Ⅰ部分CLR基础.这部分为三章(第一章:CLR的只想能够模型,第二章:生成.打包.部署和管理应用程序及类型,第三章:共享程序集和强命 ...

  8. [.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序

    [.NET MVC4 入门系列01]Helloworld MVC 4 第一个MVC4程序   一.练习项目: http://www.asp.net/mvc/tutorials/mvc-4/gettin ...

  9. 第一部分 CLR基础:第1章 CLR的执行模型

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

随机推荐

  1. 转:Android开发之旅:环境搭建及HelloWorld

    http://www.cnblogs.com/skynet/archive/2010/04/12/1709892.html 引言 本系列适合0基础的人员,因为我就是从0开始的,此系列记录我步入Andr ...

  2. MX5 ADB 链接error: device not found

    这个问题郁闷了好久,因为事情比较忙也没时间解决.每次是开启360 一键 root 勉强调试.今天狠下心把它解决了.解决办法有以下几个步骤: 1.连接方式改成 “内置光盘”,这样手机第一次连接会安装驱动 ...

  3. 第一章:Symfony2和HTTP基本原理

    恭喜你!通过学习Symfony2,你将用你自己的方式开发出更加高效.全面和流行的Web应用(当然,要受到用人单位或同行的欢迎,还是得靠你自己).Symfony2的存在是为了要解决最根本的问题:即提供一 ...

  4. 申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,立即注册可得25美元

    申请Payoneer美国万事达信用卡,可获得一个美国虚拟银行账户,可以在国内任意一个支持万事达的ATM.POS机上取现和刷卡消费.Payoneer可以网上购物,购买国外的产品,对我们有一个好处就是利用 ...

  5. Entity Framework: Joining in memory data with DbSet

    转载自:https://ilmatte.wordpress.com/2013/01/06/entity-framework-joining-in-memory-data-with-dbset/ The ...

  6. ffrpc相关文章列表

    ffrpc 是异步c++通信库.可以说是传统rpc模式和zeromq模式的一个结合,采用broker模式封装client和server之间的拓扑关系,而client和server的通信仍然按照请求应答 ...

  7. linux 笔试题

    一.填空题: 1. 在Linux系统中,以 文件 方式访问设备 . 2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统. 3. Linux文件系统中每个文件用 i节点 来 ...

  8. 安装Window Services 提示错误 [SC] OpenSCManager FAILED 5

    通过CMD注册Windows服务 之前一直这样写一直也是注册成功,今天却遇到了问题SC Manager 失败 sc create  RenService binPath=  C:\Tools\Stat ...

  9. C#的设计模式分为3大类23种

    创建型: 1. 单件模式(Singleton Pattern) 2. 抽象工厂(Abstract Factory) 3. 建造者模式(Builder) 4. 工厂方法模式(Factory Method ...

  10. SQL1159 Initialization error with DB2 .NET Data Provider, reason code 7(问题补充)

    SQL1159 Initialization error with DB2 .NET Data Provider, reason code 7 需要注册GAC,修改注册表 IBM官方方案: http: ...