写在前言
.Net Framework并不是Win 32 API 和COM上的一个抽象层。
某种程度上,它是自己的操作系统,有自己的内存管理器,自己的安全系统,自己的文件加载器,自己的错误处理机制,自己的应用程序隔离边界(AppDomains),自己的线程处理模型等。
随着多核计算机越来越普遍,线程处理,并发执行,并行结构,同步等方面的重要性日益凸显。
CLR的执行模型
公共语言运行时 CLR Common Language Runtime
是一个运行时环境,保证应用和底层操作系统之间必要的分离,是.NET Framework的主要执行引擎。是可由面向CLR的多种编程语言使用的“运行时”。CLR的核心功能(内存管理、程序集加载、安全性、异常处理和线程同步等)由面向CLR的所有语言使用。CLR不关心开发人员使用哪一种语言来写源代码。也就是说挑选编程语言时,应该选择最容易表达自己意图的语言。理论上,可以用任何语言编写代码,只要编译器是面向CLR的就可以了。
编译器
可以视为语法检查器和“正确代码”的分析器。它们检查源代码,确定你写的一切都有意义,然后输出对你的意图进行描述的代码。不同的编程语言,有着不同的语法。不要低估这个选择的价值,也许会节省大量的开发时间。
Microsoft已经创建好几个面向“运行时”的语言编译器,包括:C++/CLI、C# (C sharp)、Visual Basic、F#、Iron Python、Iron Ruby以及一个“中间语言”(Intermediate Language, IL)汇编器。
IL代码 (托管代码)
本地代码编译器是面向特定CPU架构的代码。而每个面向CLR的编译器生成的都是IL代码 (中间语言代码 )。IL代码有时称为托管代码,因为CLR要管理它的执行。它明显的优势在于它是CPU无关的。
元数据
IL代码由面向CLR的编译器产生,但它并不是编译器产生的提供给运行时仅有的东西。编译器同样产生有关原始代码的元数据。它提供给CLR关于代码更多的东西,例如:各种类型的定义、各种类型成员的签名以及其他数据。基本上,元数据是类型库、注册表内容和其它用于COM的信息。尽管如此,元数据还是直接和执行代码合并在一起,并不处在 隔离的位置。
简单地说,元数据是整个microsoft .net framework开发平台的关键,它实现了编程语言、类型和对象的无缝集成。
程序集 (assembly)
一个抽象的概念。首先,他是一个或多个模块/资源文件的逻辑性分组。其次,程序集是重用、安全性以及版本控制的最小单元。取决于你对编译器或者工具的选择,即可以生成单文件程序集,也可以生成多文件程序集。在CLR的世界中,程序集相当于一个“组件”。利用“程序集”这个概念性的东西,可以将一组文件当成一个单独的实体来对待。
对于一个可重用的、可保护的、可版本控制的组件,程序集把它的逻辑表示和物理表示分开。具体如何将代码和资源划分到不同的文件中,完全取决于个人。程序集的模块中,还包含与引用的程序集有关的信息。这些信息使程序集能够自描述(self-describing)。换句话说,CLR能够判断出为了执行程序集中代码,程序集的直接依赖对象(immediate dependency)是什么。
托管程序集同时包含元数据和IL。IL是与CPU无关的机器语言,是Microsoft在请教了外面的几个商业及学术性语言/编译器的作者之后,费劲心思开发出来的。IL比大多数CPU机器语言都要高级。IL能访问和操作对象类型,并提供了指令来创建和初始化对象,调用对象上的虚方法以及直接操作数据元素。甚至可以提供抛出和捕捉异常的指令来实现错误处理。可将IL视为一种面向对象的机器语言。
重要的提示:
允许在不同编程语言之间方便地切换,同时又保持紧密集成,这事CLR的一个非常出色的特性。遗憾的是,许多开发人员都忽视了这一特性。例如,C#和Visual Basic等语言能很多地执行I/O操作,APL语言能很好地执行高级工程或者金融计算。通过CLR,应用程序的I/O部分可用C#编写,工程计算部分则换用APL编写。CLR在这些语言之间提供了其他技术无法媲美的集成度,使“混合语言编程”成为许多开发项目的一个值得慎重考虑的选择。
执行一个方法,首先必须把它的IL转换成本地CPU指令,这是CLR的JIT (just-in-time或者“即时”)编译器的职责。JITCompiler 是CLR的一个组件,称为JITer 或者JIT编译器。它在定义(某一个类型)程序集的元数据中查找被调用的方位的IL, 接着验证IL代码,并将IL代码编译成本地CPU指令。本地CPU指令被保存到一个动态分配的内存块中。
一个方法只有在首次调用时才会造成一些性能损失。以后对该方法的所有调用都以本地代码的形式全速运行,无需重新验证IL并把它编译成本地代码。
JIT编译器将本地CPU指令存储到动态内存中,一旦应用程序终止,编译好的代码也会被丢弃。所以,如果将来再次运行应用程序,或者同时启动应用程序的两个实例(使用两个不同的操作系统进程),JIT编译器必须再次将IL编译成本地指令。
对于大多数应用程序来说,因JIT编译器造成的性能损失并不显著。大多数应用程序都会反复调用相同的方法。在应用程序运行期间,这些方法只会对性能造成一次性的影响。另外,在方法内部花费的时间很有可能比花在调用方法上的时间多得多。
还需要特别注意的是:
CLR的JIT编译器会对代码进行优化,这类似于非托管的C++编译器的后端所做的工作。同样地,可能花费较多的时间来生成优化的代码。优化之后的代码将获得更加出色的性能。
非托管的饭吗是针对一种具体的CPU平台编译的,一旦调用,代码直接就能执行。但是在托管环境中,代码的编译是分成两个阶段完成的。首先,编译器遍历源代码,做尽可能多的工作来生成IL代码,而为了真正的执行调用,这些IL代码本身必须在运行时编译成本地CPU指令,这需要分配更多的内存,并需要花费额外的CPU的时间。实践确实表明,运行时发生的第二个编译阶段会影响性能,会分配动态内存。但是,Microsoft进行了大量性能优化的工作,将这些额外的开销保持在最低限度。
IL和验证
IL是基于栈的。由于IL没有提供操作寄存器的指令,所以人们可以很容易的创建新的语言和编译器,生成面向CLR的代码。
IL指令还是“无类型”(typeless)的。例如,IL提供了一个add指令,它的作用是将压入栈的最后两个操作数加到一起。add指令不分32位和64位版本。
IL的亮点是它对底层CPU的抽象,但这并非它的最大优势。IL提供的最大的优势在于应用程序的健壮性和安全性。将IL编译成本地CPU指令时,CLR会执行一个名为验证(verification)的过程,这个过程会检查高级IL代码,确定代码所做的一切都是安全的。如,验证会核实调用的每个方法多有正确数量的参数,传给每个方法的参数都具有正确的类型,每个方法的返回值都得到了正确的使用,每个方法都具有一个返回语句等等。在托管模块的元数据中,包含了要由验证过程使用的所有方法和类型信息。
将每个windows进程都放到一个独立的地址空间,将获得健壮性和稳定性,一个进程无法干扰另一个进程。通过验证 托管代码,确保代码不会不正确的访问内存,不会干扰到另一个应用程序的代码。这样一来,就可以放心地将多个托管应用程序放到一个Windoes虚拟地址空间中运行。
CLR提供了在 一个操作系统进程中执行多个托管应用程序的能力。每个托管的应用程序都在一个AppDomain中执行。默认情况下,每个托管的exe文件都在它自己的独立地址空间中运行,这个地址空间只有一个AppDomain。然而,CLR的宿主进程(比如IIS或者MS SQL Server) 可决定在单个操作系统进程中运行多个AppDomain。
通用类型系统
CLR是完全围绕类型展开的,这一点到现在为止应该很明显了。类型为应用程序和其他类型公开了功能。通过类型,用一种编程语言写的代码能与另一种语言写的代码沟通。由于类型是CLR的根本,所以Microsoft指定了一个正式的规范,叫做“通用类型系统”(Common Type System, CTS), 描述类型定义和行为。利用了CTS指定的规则,程序集为一个类型建立了可视边界,CLR则强制(贯彻)了这些规则。
事实上,并不需要去学习CTS规则本省,你选择的语言会采用你熟悉的公式公开它自己的语言语法与类型规则。通过编译来生成程序集时,它会将语言特有的语法映射到IL -- 也就是CLR的“语言”。
CLR让我们意识到:“代码的语言”和“代码的行为”。不同语言可以定义系统的类型,添加相同的成员,语法有不同,但是类型的行为都是完全一致的,因为最终由CLR的CTS来定义类型的行为。
--------------------------------------------------------------------
- CLR via C#深解笔记七 - 自动内存管理(垃圾回收)
每个应用程序都要使用这样或者那样的资源,比如文件.内存缓冲区.屏幕空间.网络连接.数据库资源等.事实上,在面向对象的环境中,每个类型都代表可供程序使用的一种资源. 要使用这些资源,必须为代表资源的类型 ...
- CLR via C#深解笔记六 - 泛型
面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. ...
- CLR via C#深解笔记五 - 事件
事件处理实际上是一种具有特殊签名的delegate, 像这个样子:public delegate void EventHandler(object sender, EventArgs e); 类型 ...
- CLR via C#深解笔记四 - 方法、参数、属性
实例构造器和类(引用类型) 构造器(constructor)是允许将类型的实例初始化为良好状态的一种特殊方法.构造器方法在“方法定义元数据表”中始终叫.ctor. 创建一个引用类型的实例时: #1, ...
- CLR via C#深解笔记三 - 基元类型、引用类型和值类型 | 类型和成员基础 | 常量和字段
编程语言的基元类型 某些数据类型如此常用,以至于许多编译器允许代码以简化的语法来操纵它们. System.Int32 a = new System.Int32(); // a = 0 a = 1 ...
- CLR via C#深解笔记二 - 类型设计
类型基础 所有类型都从System.Object派生 CLR要求所有对象都用new 操作符来创建. Employee e = new Employee("Constructor Para ...
- 《CLR Via C#》读书笔记:26.线程基础
一.线程开销 操作系统创建线程是有代价的,其主要开销在下面列举出来了. 内存开销 线程内核对象 拥有线程描述属性与线程上下文,线程上下文占用的内存空间为 x86 架构 占用 700 字节.x64 架构 ...
- JavaScript随笔记(一)基础概念以及变量类型
一.JavaScript中的基础概念 1.defer属性 一般我们在引用外部js文件的时候往往是将引用文件的位置放在标签当中,比如那么在标签中引入多个js文件时,浏览器会按照引入顺序加载执行这些引入的 ...
- kvm学习笔记(一,基础概念)
前言 阿里云的云主机,采用的kvm,今天就花了点时间研究了下. 一.安装 官方文档参考:http://www.linux-kvm.org/page/HOWTO 二.快速建立一个基于vnc的虚拟机安装 ...
随机推荐
- ASP.NET 5系列教程 (三):view components介绍
在ASP.NET MVC 6中,view components (VCs) 功能类似于虚拟视图,但是功能更加强大. VCs兼顾了视图和控制器的优点,你可以把VCs 看作一个Mini 控制器.它负责控制 ...
- 1119 网页布局,css写下拉列表
<style type="text/css"> *{ margin:0px; padding:0px;} #body{ width:1000px; height:200 ...
- Atitit WebDriver技术规范原理与概念
Atitit WebDriver技术规范原理与概念 1. Book haosyo ma1 2. WebDriver是W3C的一个标准,由Selenium主持.1 3. WebDriver如何工作 (z ...
- paip.python NameError name 'xxx' is not defined\
paip.python NameError name 'xxx' is not defined\ 导入一个另一个文件里面的函数的时候儿,出孪这个err #这个仅仅导入孪file...要使用里面的fun ...
- paip.log4j兼容linux windows 路径设置
paip.log4j兼容linux windows 路径设置 作者Attilax 艾龙, EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog ...
- 【转】Oracle 执行动态语句
1.静态SQLSQL与动态SQL Oracle编译PL/SQL程序块分为两个种:其一为前期联编(early binding),即SQL语句在程序编译期间就已经确定,大多数的编译情况属于这种类型:另外一 ...
- iOS开发——高级技术&社交服务
社交服务 Social 现 在很多应用都内置“社交分享”功能,可以将看到的新闻.博客.广告等内容分享到微博.微信.QQ.空间等,其实从iOS6.0开始苹果官方就内置了 Social.framework ...
- MySql的基本操作以及以后开发经常使用的常用指令
第一章:数据类型和操作数据表MySQL语句的规范(1):关键字与函数名称全部大写(2):数据库名称,表名称,字段名称全部小写(3):SQL语句必须以分号结尾 1:命令行模式启动mysql服务net s ...
- Django简介
Django, 应该读作jan go,读音演示 D是不发音的---发音的---音的---的--- django简介:urls.py网址入口,关联到views.py views.py处理用户发出的请求, ...
- DOM基本概念和操作
1.基本概念 DOM是文档对象模型(TEXT),对象是指文档中的每一个元素. 2.Window对象操作 打开方式: _blank 在新窗口还是自身窗口. Window.open 也有返回值,返回值为 ...