组件对象模型(Component Object Mode, COM)是 CLR 的前身,它将 Windows 平台上运行的所有成员标准化,并定义了它们之间沟通的规范,使得不同编程语言的进程间通信和动态对象创建成为可能。
所有 COM 组件都实现了 IUnknown 接口,采用引用计数管理对象的生命周期。
当微软开始 .NET 框架的开发时,他们最终决定改进现有的 COM,并将它命名为公共语言运行时(Common Language Runtime, CLR)。
CLR 中组件间的沟通规范由元数据 (metadata)负责,因此,每个可迁移执行文件(即 .exe 文件)都包含了元数据,以便 CLR 知道文件内部的类型是什么。
所以,有人称“CLR 是一个更好的 COM”。
CLR 是让 .NET 程序执行所需的外部服务的集合,.NET 平台的核心和最重要的组件,类似于 Java 的 JVM。
它有如下的核心功能:
- 在程序的第一步编译时,将程序通过对应的编译器编译为 IL,并生成元数据。将 IL 和元数据打包,加入 PE 和 CLR 文件头使之成为托管模块,将各个模块打包为程序集(不过,语言编译器不被看作 CLR 的一部分)。
- 程序执行时,类型检查器负责保证类型安全(代码验证),即时编译器(JIT)负责将 IL 编译为机器码。
- 类型加载器(Class loader)负责通过清单和元数据探测类型的位置,并加载需要的类型,生成类型对象,包括方法表等。
- 方法调用。
- 自动内存管理和垃圾回收(COM 使用引用计数,而 CLR 使用标记清除)。
- 线程池管理。
- 字符串驻留池管理。
- 异常处理。
- 动态加载程序集(晚期绑定),这是和类型加载器交互的必然结果。
- 与 COM 组件的交互。
可以看到,绝大部分功能都是在程序运行时保证程序的顺利执行的。
因此,CLR 管理 .NET 程序集的执行,运行于操作系统之上。
CLR 的一些功能仅仅是操作系统的一个再包装,例如线程,内存管理等,这些实际上是进一步调用操作系统 API,访问内核对象。
但 JIT 则是它独有的,如果没有它,就不能把 IL 变成机器码,计算机也就不认识 C#,你也就不能运行 C# 程序。
对 CLR 了解越多,对整个 .NET 的把握就越好。
托管代码是必须在 CLR 下执行的代码,而非托管代码则不需要 CLR 的支持就可以运行。
CLR 本身用于管理托管代码,因此它是由非托管代码编写的,而并不是一个包含了托管代码的程序集,也不能使用基于 IL 的反编译工具进行查看。
CLR 位于 C:/%SystemRoot%/Microsoft.NET/Framework/[ 版本号 ]下,对应不同的机器有两个版本,一个是工作站版本的 mscorwks.dll,一个是服务器版本的 mscorsvr.dll。
wks 和 svr 分别代表 workstation(工作站) 和 server(服务器)。
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/22359.html