好吧,废话少说,先上一章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. Java 部分排序算法

    . import java.io.*;import java.math.*;import java.util.*;public class Algr{ public static int array[ ...

  2. Multiple Contexts have a path of "/xxxx"问题解决

    转自:http://blog.csdn.net/ivanzhangqf/article/details/50326533 之前因为ecplise项目保存更新时一直显示等待后台操作完成,以至于一直卡住无 ...

  3. iOS 实现快速切换主题详细教程(附上源码)

    前言 iOS 实现主题切换,相信在未来的app里也是会频繁出现的,尽管现在只是出现在主流的APP,如(QQ.新浪微博.酷狗音乐.网易云音乐等),但是现在是看颜值.追求个性的年代,所以根据用户喜好自定义 ...

  4. C++虚函数与虚函数表

    多态性可分为两类:静态多态和动态多态.函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的. 每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说 ...

  5. 谷歌面经 Tree Serialization

    http://www.careercup.com/question?id=4868040812396544 You should transform an structure of multiple ...

  6. [PaPaPa][需求说明书][V0.1]

    PaPaPa软件需求说明书V0.1 前   言 我觉得我们废话不能多,废话一多的话大家就找不到重点了,其实本项目是出于技术研究的目的来开发的,大家讨论了半天决定要做社(yue)交(pao)类的项目. ...

  7. sloth——算法工程师标注数据的福音

    一般算法工程师做标注,都要先开发个标注工具,无非下面几个选项: 1.mfc,C#,优点是交互界面友好,开发难度适中,缺点是没法跨平台 2.matlab,优点是可以跨平台,开发难度非常低,缺点是速度慢. ...

  8. android html 与webview属性从冲突

    在最近的项目开发中,使用webview加载html页面,这样可以节省大量页面开发的时间,同时也可加快项目进度. 我们需求是需要显示商品评论,页面设计如下: 调用android代码,对于webview的 ...

  9. Nginx模块开发时unknown directive "echo"的处理

    实际上,Nginx并没有echo这个指令,所以你贸然使用时,自然会提示说无法识别的指令,处理方法有两个: 方法一是: 从下面连接下载echo-nginx-module模块并安装: https://gi ...

  10. 编译安装 LLVM

    本文记录 LLVM 的安装过程,比较繁琐,使用 LLVM 3.4 操作系统:CentOS 6.6 64 位 1. 下载需要的软件 相关软件下载地址:http://llvm.org/releases/d ...