zoukankan      html  css  js  c++  java
  • Unity 深度理解C# 的执行原理及Unity跨平台 笔记

    笔记

    • 编译器的工作流水线:
    • 源代码-词法分析-语法分析-语义分析-目标代码-链接-可执行文件 (现代编译器会更复杂,比如优化)
    • 虚拟机执行中间代码的方式分为 2 种:解释执行和 JIT(即时编译)。解释执行即逐条执行每条指令,JIT 则是先将中间代码在开始运行的时候编译成机器码,然后执行机器码。
    • C# 编译 CIL语言,放到CLR虚拟机内执行 (CIL,Common Intermediate Language,也叫 MSIL)
    • .Net Framework定义:通常我们把 C#、CIL、CLR,再加上微软提供的一套基础类库称为 .Net Framework
    • Mono 是跨平台的 .Net Framework 的实现。Mono 做了一件很了不起的事情,将 CLR 在所有支持的平台上重新实现了一遍,将 .Net Framework 提供的基础类库也重新实现了一遍。
    • 理论上,你创造了一门语言,并且实现了所有平台下的编译器,就能跨语言了。

    原文

    为什么 Unity3D 可以运行 C#,C# 和 Mono 是什么关系,Mono 和 .Net Framework 又是什么关系?我们深入的来聊一聊这个话题!

    从编译原理说起

    一句话介绍编译器:编译器是将用某种程式语言写成的源代码(源语言),转换成另一种程式语言(目标语言)等价形式的程序。通常我们是将某种高级语言(如C、C++、C# 、Java)转换成低级语言(汇编语言、机器语言)。
    编译器以流水线的形式进行工作,分为几个阶段:源代码 → 词法分析 → 语法分析 → 语义分析 → 目标代码 → 链接 → 可执行文件。
    链接(linking)解释:上一步骤的结果可能会引用外部的函数,把外部函数的代码(通常是后缀名为.lib和.a的文件),添加到可执行文件中,这就叫做链接。——两种,静态链接(编译时)和动态链接(runtime)。

    现代编译器还会更复杂,中间会增加更多的处理过程,比如预处理器,中间代码生成,代码优化等。

    虚拟机是什么

    虚拟机(VM),简单理解,就是可以执行特定指令的一种程序。为了执行指令,还需要一些配套的设施,如寄存器、栈等。虚拟机可以很复杂,复杂到模拟真正的计算机硬件,也可以很简单,简单到只能做加减乘除。
    在编译器领域,虚拟机通常执行一种叫中间代码的语言,中间代码由高级语言转换而成,以 Java 为例,Java 编译后产生的并不是一个可执行的文件,而是一个 ByteCode (字节码)文件,里面包含了从 Java 源代码转换成等价的字节码形式的代码。Java 虚拟机(JVM)负责执行这个文件。
    虚拟机执行中间代码的方式分为 2 种:解释执行和 JIT(即时编译)。解释执行即逐条执行每条指令,JIT 则是先将中间代码在开始运行的时候编译成机器码,然后执行机器码。由于执行的是中间代码,所以,在不同的平台实现不同的虚拟机,都可以执行同样的中间代码,也就实现了跨平台。

    int run(context* ctx, code* c) {
        for (cmd in c->cmds) {
            switch (cmd.type) {
                case ADD:
                // todo add            break;
                case SUB:
                // todo subtract            break;
                // ...        }
        }
        return 0;}
    

    总结一下,虚拟机本身并不跨平台,而是语言是跨平台的,对于开发人员来说,只需要关心开发语言即可,不需要关心虚拟机是怎么实现的,这也是 Java 可以跨平台的原因,C# 也是同样的。推而广之,理论上任何语言都可以跨平台,只要在相应平台实现了编译器或者虚拟机等配套设施。

    C# 是什么,IL 又是什么

    C# 是微软推出的一种基于 .NET 框架的、面向对象的高级编程语言。微软在 2000 年发布了这种语言,希望借助这种语言来取代Java,更多详细的介绍可以参看 C# Wiki。
    C# 是一个语言,微软给它定制了一份语言规范,提供了从开发、编译、部署、执行的完整的一条龙的服务,每隔一段时间会发布一份最新的规范,添加一些新的语言特性。从语法层面来说,C# 是一个很完善,写起来非常舒服的语言。
    C# 和 Java 类似,C# 会编译成一个中间语言(CIL,Common Intermediate Language,也叫 MSIL),CIL 也是一个高级语言,而运行 CIL 的虚拟机叫 CLR(Common Language Runtime)。通常我们把 C#、CIL、CLR,再加上微软提供的一套基础类库称为 .Net Framework。

    C# 天生就是为征服宇宙设计的,不过非常遗憾,由于微软的封闭,这个目标并没有实现。当然 C# 现在还过得很好,因为游戏而焕发了新的活力,因为 Unity3D,因为 Mono。

    .Net Framework vs Mono

    Mono 是跨平台的 .Net Framework 的实现。Mono 做了一件很了不起的事情,将 CLR 在所有支持的平台上重新实现了一遍,将 .Net Framework 提供的基础类库也重新实现了一遍。

    以上,Compile Time 的工作实际上可以直接用微软已有的成果,只要将 Runtime 的 CLR 在其他平台实现,这个工作量不仅大,而且需要保证兼容,非常浩大的一个工程,Mono 做到了,致敬!
    Unity3D 中的 C#
    Unity3D 内嵌了一个 Mono 虚拟机,从上文可以知道,当实现了某个平台的虚拟机,那语言就可以在该平台运行,所以,严格的讲,Unity3D 是通过 Mono 虚拟机,运行 C# 通过编译器编译后生成的 IL 代码。
    Unity3D 默认使用 C# 作为开发语言,除此之外,还支持 JS 和 BOO,因为 Unity3D 开发了相应的编译器,将 JS 和 BOO 编译成了 IL。
    小结
    C# 在 Windows 下,是通过微软的 C# 编译器,生成了 IL 代码,运行在 CLR 中。
    C# 在除 Windows 外的平台下,是通过 Mono 的编译器,生成了 IL 代码,运行在 Mono 虚拟机中,也可以直接运行将已经编译好的 IL 代码(通过任意平台编译)。
    理论上,你创造了一门语言,并且实现了某一平台下的编译器,然后实现了所有平台下符合语言规范的虚拟机,你的语言就可以运行在任意平台啦。

    IL2CPP, IL2CPP VM

    本 文的主角终于出来了:IL2CPP。有了上面的知识,大家很容易就理解其意义了:把IL中间语言转换成CPP文件。大家如果看明白了上面动态语言的 CLI, IL以及VM,再看到IL2CPP一定心中充满了疑惑。现在的大趋势都是把语言加上动态特性,哪怕是c++这样的静态语言,也出现了适合IL的c++编译 器,为啥Unity要反其道而行之,把IL再弄回静态的CPP呢?这不是吃饱了撑着嘛。根据本文最前面给出的Unity官方博客所解释的,原因有以下几 个:
    1.Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成
    Mono的跨平台是通过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM肯定是不能满足需求的。所以针对不同的新平 台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这非常耗时耗力。这些能移植的平台还好说,还有比如WebGL这样基于浏览 器的平台。要让WebGL支持Mono的VM几乎是不可能的。
    2.Mono版本授权受限
    大家有没有意识到Mono的版本已经更新到3.X了,但是在Unity中,C#的运行时版本一直停留在2.8,这也是Unity社区开发者抱怨的最多一 条:很多C#的新特性无法使用。这是因为Mono 授权受限,导致Unity无法升级Mono。如果换做是IL2CPP,IL2CPP VM这套完全自己开发的组件,就解决了这个问题。
    3.提高运行效率
    根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升

    https://zhuanlan.zhihu.com/p/19972689

    转:深度理解C# 的执行原理

  • 相关阅读:
    java Activiti 工作流引擎 SSM 框架模块设计方案
    自定义表单 Flowable 工作流 Springboot vue.js 前后分离 跨域 有代码生成器
    数据库设计的十个最佳实践
    activiti 汉化 stencilset.json 文件内容
    JAVA oa 办公系统模块 设计方案
    java 考试系统 在线学习 视频直播 人脸识别 springboot框架 前后分离 PC和手机端
    集成 nacos注册中心配置使用
    “感恩节 ”怼记
    仓颉编程语言的一点期望
    关于System.out.println()与System.out.print("\n")的区别
  • 原文地址:https://www.cnblogs.com/Jaysonhome/p/13218403.html
Copyright © 2011-2022 走看看