重学c#系列——c#运行原理(二)
前言
c# 是怎么运行的呢?是否和java一样运行在像jvm的虚拟机上呢?其实差不多,但是更广泛。
c# 运行环境不仅c#可以运行,符合.net framework 开发规范的都可以运行。
c# 程序在.net framework 上运行,而这个.net framework是windows独有的,所以这就是为什么以前c#不跨域的原因,现在c#可以运行在.net core 上,而.net core 跨平台还跨语言。
无论.net core还是.net framework都包括名为(公共语言运行时(CLR))的虚执行系统和一组统一的类库。
正文
什么是CLR
下面是对CLR的介绍:
CLR 是由 Microsoft 执行的公共语言基础结构 (CLI) 的商业实现,CLI 是作为执行和开发环境(语言和库在其中无缝协作)创建依据的国际标准。
这样解释似乎不够通俗,那么它到底干了啥呢。
举几个例子:
(1)类加载器:管理元数据,加载和在内存中布局类;
(2)Micorsoft 中间语言(MSIL)到本地代码编译器:通过即时编译把Micorsoft 中间语言转换为本地代码;
(3)代码管理器:管理和执行代码;
(4)垃圾回收器:为NET.Framework下的所有对象提供自动生命期管理,支持多处理器,可扩展;
(5)安全引擎:提供基于证据的安全,基于用户身份和代码来源;
(6)调试器:使开发者能够调试应用程序和根据代码执行;
(7)类型检查器:不允许不安全的类型转换和未初始化变量MSIL可被校验以保证类型安全。
这样一看这和java 的虚拟机非常像啊,这东西难道就是虚拟机。
下面这种图,一看就更像了啊:
不管是什么语言,在.net 平台上开发,然后转换成MSIL语言(这里解释一下为什么CLR为什么叫公共语言运行时,因为只要能编译成MSIL就能在这上面运行),然后通过CLR运行在windows上。
那么CLR 是否是像JVM一样的虚拟机呢?
CLR是一个支持多种编程语言及多语言互操作,完整的高级虚拟机。他们做的事情差不多,但是他们的实现原理和运行方式差异巨大。
具体可参考:https://github.com/dotnet/coreclr/blob/master/Documentation/botr/intro-to-clr.md
既然CLR是一个运行公共语言的虚拟机,运行的还是MSIL语言,那么这个MSIL语言是怎么来的呢?这就是微软贡献特别大的地方了,微软向ECMA提供了一份公共语言开发的规范。
下面贴一下概念:
·CLR(公共语言运行库)是一个CLI的实现,包含了.NET运行引擎和符合CLI的类库。我们开发的几乎所有的.NET程序都基于CLR的类库来实现,并且运行在CLR提供的运行引擎之上。
·CLI(公共语言基础)是微软公司向ECMA提交的一份语言和数据格式规范,CLR是目前为止唯一一个公共语言基础的实现版本。CLI包括了公共类型系统(CTS)、公共中间语言(CIL)、底部文件格式以及元数据格式等
·CTS(公共类型系统)定义了一个能够在CLR上运行的语言规范。尽管有很多语言本身不符合CTS规范,但是通过加强编译器,改变语言附加规范等手段,使得许多语言能够编写出能在CLR上运行的程序。
一种语言编写的程序编译能够在CLR上运行,并不代表这种语言本身完全符合CTS的规范。例如C++语言,仍然保持了其不符合CTS规范的部分,并且在编译时把这部分不符合CTS的代码编译成原始代码而非中间代码。
·CLS(公共语言规范)是CTS的一个子集,它定义了希望编写在.NET平台上运行的程序的语言所需符合的最小规范。正因为.NET允许由不同语言编写的程序一起执行,所以才制定出CLS规范,
用以避免不同语言特性产生的错误。在.NET Framework中,几乎所有(但不是所有)的类都是与CLS兼容的。在MSDN文档说明中,不兼容的类和方法都被特别标记为不兼容,例如System命名空间中的UInt32结构。
UInt32表示32位无符号整数。并不是所有的语言(例如Visual Basic.NET或J#)都支持无符号的数据类型,这种数据类型是与CLS不兼容的。
既然是介绍c#,那么就看下c# 到CLR的运行过程吧。如下图:
由上图可以看到只需要修改下面部分,即可实现将原来windows的那一套搬运到不同的平台上。
现在的.net core就是通过修改这部分来实现跨平台的,真的是大手笔。以前有一个mono(Mono根据C#和CLR的ECMA标准实现了一份Linux下的CLR,比如说,Linux里没有注册表的概念,Mono用一个.ini文件来模拟注册表。),
我尝试使用过,小型网站用用还是可以的(老项目没有windows主机可以放一下),效率的确低了一些,只是尝试部署过一次。
.NET Standard
这东西比较关键,是一套规范。
官方文档这样介绍道:
NET Standard 是一套正式的 .NET API 规范,有望在所有 .NET 实现中推出。
推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。
ECMA 335 继续为 .NET 实现行为建立统一性,尽管 ECMA 335 指定了一小组标准库,但 .NET Standard 规范包含范围更广的 .NET API。
这东西伴随着.net core 一起诞生。
这东西出现是解决这样一个问题的。
现在有.net framewore还有.net core,那么就有一个问题啊,都是用c#在不同平台上开发,他们调用的api是否一致呢?
比如说有个在.net framework 上有个叫做System.IO.FileSystem的api库,那么在.net core上文件操作是否也叫这个呢?
所以为了统一就制定了一套规范,叫做标准库,是.net framework和.net core 都有的,有些是.net core上没有的,比如D3D只有windows操作系统上有,Linux根本就没有这个东西,所以不会加入标准库。
同理用标准库开发的东西是可以在两套平台上跑的。
NET Standard 一直在更新,这是历史原因,那就是当时出来.net core的时候有些api是.net framework 有但是.net core没有的,这个也不是说是windows都有的api,而是说当时来不及。
NET Standard 2.0 中的新增功能这样写道:
.NET Standard 2.0 新增了以下功能:
大幅扩展了 API 集
.NET Standard 版本 1.6 中包含了相对较小的一部分 API。
不包含的 API 许多都是 .NET Framework 或 Xamarin 中的常用 API。
这样一来,开发变得更为棘手,因为开发人员必须在开发定目标到多个 .NET 实现的应用和库时,寻找常用 API 的合适替代项。
为了消除此限制,.NET Standard 2.0 向 Standard 旧版本 .NET Standard 1.6 中的可用 API 补充了 20,000 多个 API。
随着时间的推移,.net core现在开发就比较轻松了。