第一章 Microsoft .NET框架开发平台体系结构
Ø 1.1将源代码编译为托管模块
在非托管C/C++中,我们可以对系统有着相当底层的控制,我们可以以自己喜欢的方式来管理内存。
不管使用的是何种编译器,最后生成的结果都是一个托管模块(Managed Module)。托管模块是一个需要CLR才能执行的编准可移植可执行文件(portable executable,简称PE)文件。
PE文件的各个组成部分
1. PE表头 指出文件的类型
2. CLR表头 包含标识托管模块的一些信息
3. 元数据 主要包含两种元数据表,一种用于描述源代码中定义的类型及成员,一种用于描述源代码中引用的类型和成员
4. 中间语言(IL)代码 编译器在编译源代码中产生的指令
由于生存期和执行行为受CLR管理的缘故,IL代码有时也被称为托管代码(Managed Code)。
元数据总是和包含IL代码的文件相关联,并被嵌入到同一个EXE/DLL文件中。
元数据的用处:
1. 省去了源代码编译时对头文件和库文件的需求,编译器可以直接从托管模块的元数据中来获取所有被引用的类型和成员的信息
2. VS可以利用元数据来辅助我们编码 主要是IDE的IntelliSense功能
3. CLR的代码验证过程可以利用元数据来确保代码仅执行“安全”的操作
4. 利用元数据可以进行序列化与反序列化
5. 利用元数据,垃圾收集器可以跟踪对象的生存期
C++可以允许开发人员同时编写托管代码和非托管代码,并且可以将它们生成到同一个模块中
Ø 1.2 将托管模块组合为程序集
CLR不与托管模块大交道,它直接打交道的对象是程序集。程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。其次,程序集是组合复用,以及实施安全策略和版本策略的最小单位。
PE文件中还包含一个称作清单的数据块,所谓的清单仅仅是另外一些元数据表的集合,这些表描述了组成程序集的文件,程序集所有文件中实现的公有导出类型,以及一些和程序集相关的资源文件或数据文件。
默认情况下,编译器会将产生的托管模块转换为一个程序集。
程序集中的模块包含一些它所引用的程序集的一些信息使得程序集得以实现自描述。换句话说,CLR知道执行一个程序集所需要的所有内容,因此不需要再在注册表或活动目录中获取额外的信息,因此,程序集的部署要比非托管组件的部署要快的多。
Ø 1.3 加载通用语言运行时
程序集分两种: .exe(可执行,有应用程序入口点)与.dll
.exe加载并初始化CLR过程:
1. MSCorEE检查CLR表头以获得Main方法的元数据标记
2. MSCorEE检查Main方法的元数据以获得其IL在托管EXE中的位置
3. MSCorEE将Main方法的IL编译为本地CPU指令
4. MSCorEE跳转到编译后的本地CPU指令上
Ø 1.4 执行程序集代码
IL可以被视为一种面向对象的机器语言
开发通用语言基础构造(Common Language Infrastructure,CLI),其是CLR和.NET框架类库的一个子集,其定义了文件格式,CTS,可扩展元数据系统,IL,底层平台访问(P/Invoke)共五项标准,另外CLI还定义了一个允许多种编程语言使用的,裁减了的基础类库。
尽管目前的CPU还不能直接执行IL指令,但经来的CPU也许会具有这种能力。
JIT负责将IL代码编译为本地CPU指令。
JIT Compiler第一次编译IL过程:
1. 根据程序集元数据搜索被调用方法的IL代码的位置
2. 动态分配一个内存块
3. 验证代码安全并将它们编译为本地CPU指令
4. 将CPU指令存储在内存块中
5. (应该是从元数据中)修改被调用方法的地址为内存块地址
6. 跳转到内存块中的本地CPU指令上
JIT Compiler第二次编译IL过程:
1. 直接调用内存块中已有的本地CPU指令,完全跳过JIT的验证与编译过程
当应用程序关闭时:
编译生成的本地CPU指令将被丢弃
非托管代码是针对某一特定CPU平台所编译的,当它们被调用时,这些代码将会立即执行。在托管环境中,代码的编译要经过两个阶段才能完成:
1. Build 编译器扫描源代码,将其编译为IL代码
2. Execute 执行这些IL代码,它们还必须在运行时被编译成本地CPU指令,这项工作通常会耗费很多内存,且花费更多的时间
C/C++编写的非托管代码不会有托管代码第二步分配的额外开销,性能比较好
可以使用NGen.exe工具将一个程序集中所有的IL代码转化为本地代码,并将结果代码保存在磁盘上的一个文件上
Ø 1.4.1 IL与代码验证
IL是一种基于堆栈的语言,它所有指令或者是将操作数推进一个执行堆栈中,或者是从堆栈中弹出结果
IL的最大优势:提高了应用程序的健壮性。当IL代码被编译为本地CPU指令时,CLR将执行一个称作验证的过程。
安全代码的好处:我们可以在一个单独的Windows虚拟地址空间内运行多个托管应用程序,减少了进程的数量,从而提高系统性能,降低资源需求,而应用程序仍然可以保持很好的健壮性。
在CLR中,托管应用程序被称为应用程序域(AppDomain)
Ø 1.5 .NET框架类库
在.NET框架中包括有一组.NET框架类库(Framework Class Library,FCL)程序集,包含了几千个类型的定义。
Ø 1.6 通用类型系统
CTS是一个规范,用来描述类型的定义和行为,其还定义了类型的可见性和访问类型成员的一些规则。CTS还定义了诸多规则来管理类型继承,虚函数,对象生存期等事项。
Ø 1.7 通用语言规范
CLS 是一个规范,规定了面向CLR的编译器必须支持的一个最小特性集合,其所规定的内容是CTS的一个子集。
使用IL汇编语言的开发人员将能够利用CLR/CTS提供的所有特性;而大多数其它语言,例如C#,提供给开发人员的将是CLR/CTS特性的一个子集;CLS定义的是所有语言必须支持的一个最小特性集合。
Ø 1.8 与非托管代码互操作
CLR支持的三种互操作情形:
1. 托管代码调用DLL中的非托管函数
2. 托管代码使用现存的COM组件(非托管组件为COM服务器)
3. 非托管代码使用托管类型(托管类型作为COM服务器)