C#编译过程

很多人只知道c# 应用程序运行 必须有CLR(公共语言运行时)和.net框架的支持,但不知道为啥需要?

    其实很简单,因为.exe只是IL指令,CIL(公共中间语言),目前的CPU还不能直接执行IL指令,但将来的CPU也许会具有这种能力。执行exe它的IL代码还必须首先被转换成为本地CPU指令,这属于CLR中即时编译器的工作。总所周知,程序入口点是Main函数,在程序执行之前,CLR检测Main中代码所引用到的所有类型,分配多个内部的数据结构,一个类对应一个数据结构,类中每个方法都会有一个对应的条目,每个条目保存有一个方法实现代码的地址。

    当Main函数第一次调用程序中的某个方法时,JITCompiler函数将被调用,也就是将该方法的IL代码编译成本地的CPU指令,注意这是即时编译的,这些本地CPU指令将被保存在一个动态分配的内存块中,然后JITCompiler将前面内部数据结构中被调用方法的地址替换为包含本地CPU指令的内存块地址。最后JITCompiler将跳转到该内存块的代码上。这就是即时编译所做的工作,当该方法执行完毕,它将返回到Main函数中,继续执行下面的代码。

    Main函数第二次调用程序的某个方法时,该方法的IL已经被编译成CPU指令,所以这一次执行将直接调用内存块中已有的本地代码,也正因为如此,一个方法只有在首次调用时才会产生一些性能上的损失。但所有对该方法的后续调用都将以本地代码全速执行。

    JIT编译器将本地代码存储于动态内存之中,这就意味着关闭程序时,编译生成的本地代码将会被丢弃。再次运行程序依旧要把IL代码转换为CPU指令,这就是为什么每次运行都需要CLR及.net框架支持的原因。

 

C#语言运行时要经过两次编译,第一次编译是将源代码编译为MSIL(微软中间语言),即可以发布软件了。当软件运行时MSIL代码载入内存时会进行第二次编译,中间语言会编译为机器语言以供计算机调用,第二次编译只在载入内存时发生,编译的结果被储存起来以备重复利用。编译时是按需编译,即只编译所用到的代码,而不是全部程序,称为JIT(即时编译)。

编译过LINUX的朋友应该都熟悉Make文件吧,在这里面可以清楚的看到使用编译器把C源代码编译成二进制源代码的流程,中间干了什么都可以看得清清楚楚。但使用VS的朋友一般都是程序写好之后直接F5就运行了,后面做了什么我们根本不知道。对于COSMOS的源代码,VS只是帮我们编译成了IL的代码,这种代码无法在没有CLR环境中运行,所以VS还需要把IL代码编译为针对CPU的本地代码。这中间的流程都由MSBuild这个东西控制。对于MSBuild的介绍可以直接查看MSDN文档。总的来说这个东西的地位就相当于Make文件的地位吧,指导VS如何生成可以引导的二进制文件。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值