咱小谈CLR
1.什么是CLR
CLR(Common Language Runtime)公共语言远行时,是一个可由多种编程语言使用的“远行时”。CLR的核心功能(比如内存管理、程序集加载、安全性、异常处理和线程同步)可由面向CLR的所有语言使用。CLR不关心开发人员使用哪种语言进行编程,只要编译器面向CLR就可以了,所有,开发人员应该使用自己最适合和熟悉的语言进行编程。所有的编程语言在面向CLR编译器的编译都生成了一个托管模块。托管模块是一个标准的32位的Microsoft Windows可移植执行体(PE32)文件,或者是一个标准的64位Windows可移植的PE32+文件,他们都需要CLR才能执行。
2.托管模块的各个组成部分
PE32或PE32+头 标准Windows PE文件头,类似于“公共对象文件格式”。
CLR头 包含使用这个模块成为一个托管模块的信息(可由CLR和一些实用程序进行解释)。头中包含了需要的CLR版本,一些标志,托管模块人口方法(Main方法)的MethodDef元数据标记(token),以及模块的元数据、资源、强名称、一些flag以及其他不太重要的数据项的位置/大小
元数据 每个托管模块都包含元数据表。主要有两种类型的表:一种类型的表描述源代码中定义的类型和成员:另一种类型的表描述源代码引用类型和成员
IL(中间语言)代码 编译器编译源代码时生成的代码。在运行时,CLR将将IL编译成本地的CPU指令
元数据的用途:
编译时,元数据消除了对本地C/C++头和库文件的需求,因为在负责实现类型/成员的IL代码中,已包和引用的类型/成员有关的全部信息。编译器可直接从托管模块读取元数据
Microsoft Visual Studio 使用元数据帮助你写代码。也就是“智能感知(IntelliSense)技术”可以解析元数据,指出一个类型提供了那些方法、属性、事件和字段等等。
CLR的代码验证过程使用元数据确保代码只执行“类型安全”的操作。
元数据允许将一个对象的字段序列化到一个内存中,将其发送给另一台机器,然后反序列化,在远程机器上重建对象的状态
元数据允许垃圾回收器跟踪对象的生存期。垃圾回收器能判断任何对象的类型,并从元数据知道那个对象中的哪些字段引用了其他对象。
3.程序集
其实,CLR不和托管模块一起工作。它和程序集(assembly)一块工作。程序集是一个或多个模块/资源文件的逻辑分组。程序集是重用、安全性已经版本控制的最小单元。程序集是自描述的(self-describing)
4 执行程序集的代码
托管程序集同时包含元数据和IL。为了执行程序,首先必须把它的IL转换成本地CPU指令。这是CLR的JIT(just-in-time)编译器的职责。
下面我将复述一下一个书的例子来说明一个程序集中的代码是如何执行的。
在Main方法执行之前,CLR会检测出Main的代码引用的所有类型。这将导致CLR分配一个内部数据结构,它用来管理对所用引用的类型的访问。例如上图,Main方法引用了一Console类型,这导致CLR分配一个内部结构。在这个内部结构中,Console类型定义的每个方法都有一个对应的记录项。每个记录项都容纳一个地址,根据此地址既可以找到方法的实现。对这个结构进行初始时,CLR将每个记录项都设置成(指向)包含在CLR内部的一个未文档化的函数。我将这个函数成为JITCompiler。
Main首次调用WriteLine时,JITCompiler函数会被调用。JITCompiler函数负责将一个方法IL代码编译成本地CPU指令。由于IL是“即时”(just in time)编译的,所以通常CLR的这个组件称为JITter或者JIT编译器。
JITCompiler函数被调用时,它知道要调用的是哪个方法,以及具体是什么类型定义了该方法。然后,JITCompiler会在定义程序集的元数据中查找被调用的方法的IL。接着,JITCompiler验证IL代码,并将IL代码编译成本地CPU指令。本地CPU指令被保存到一个动态分配的内存块中。然后,JITCompiler返回CLR为类型创建的内部数据结构,找到与被调用的方法对象的那一条记录,修改最初对JITCompiler的引用,让它现在指向内存块中的地址。最后,JITCompiler函数跳转到内存块中的代码。
第二次调用WriteLine。这一次,由于对WriteLine的代码进行了验证和编译,所以直接执行内存块中的代码,完全跳过JITCompiler函数。
第二次调用WriteLine的情况
5.通用类型系统
为了通过类型,用一种编程语言写的代码能与用另一种语言写的代码沟通,Microsoft指定了一正式的规范,即“通用类型系统”(Common Type System,CTS),它描述了类型的定义和行为。
CTS规范规定,一个类型可以包含零个或多个成员。
字段(Field) 一个数据变量
方法(Method) 一个函数
属性(Property) 对于调用者,该成员看起来像是一个字段
事件(Event) 事件在对象以及其他相关对象之间实现了一通用机制。
CTS 还指定了类型可视性规则以及类型成员的访问规则,例如private,family等
CTS还为类型继承。虚方法、对象生存期等定义了相应的规则
特比说一下CTS中的一条规则:所有类型最终必须从预定义的System.Object类型继承。System.Object可以做的事情如下:
比较两个实例的相等性
获取实例的哈希码
查询一个实例的真正类型
执行实例的浅拷贝
获取视实例对象的当前状态的一个字符串表示
6.公共语言规范
为了创建很容易从其他编程语言中访问的类型,只能从自己的编程语言中挑选其他所有语言都确定支持的那些功能,Microsoft定义了一个“公共语言规范”(Common Language Specifiaction,CLS),它详细定义了一个最小功能集。
7.元数据
上面已经提到托管的PE文件由4个部分构成:PE32(+)头、CLR头、元数据以及IL。
这里我们主要说一下元数据。
元数据是一个二进制数据块,由几个表构成。这些表分为三个类别:定义表(definiton talbe)、引用表(reference table)和清单表(mainfest table)。
常用元数据定义表(编译器编译源代码时,代码定义的任何一样东西都会导致定义表中的表中创建一个记录项):
ModuleDef 总是包含一个用于标示模块的记录项。
TypeDef 模块中定义的每个类型都在这个定义表中有一个对应的记录项。
MethodDef 模块中定义的每个方法都在这个定义表中有一个对应的记录项。
FieldDef 模块中定义的每个字段都在这个定义表中有一个对应的记录项
ParamDef 模块中定义的每个参数都在这个定义表中有一个对应的记录项
PropertyDef 模块中定义的每个属性都在这个定义表中有一个对应的记录项
EventDef 模块中定义的每个事件都在这个定义表中有一个对应的记录项
常用的引用元数据表:
AssemblyRef 模块中引用的每个程序集在这个表中都有一个对应的记录项
ModuleRef 模块引用的每个类型可能是由别的PE模块实现的,所有那些模块在这个表都有一个记录项
TypeDef 模块引用的每个类型在这个表中都有一个对应的记录项
MemberRef 模块引用的每个成员都在这个表中有一个对应的记录项
清单元数据表:
AssemblyDef 如果该模块标示的是一个程序集,就在这个元数据表中包含单个记录项。该记录项列出了程序集名称(不含路径和扩展名)、版本(major,minor,build和revision)、语言文化(culture)、一些标志(flag)、哈希算法以及发布者的公钥。
FileDef 作为程序集一部分的每个PE文件和资源文件在这个表中都有一个对应的记录项。
MainifestResourceDef 作为程序集一部分的每个资源在这个表中都有一个对应的记录项
ExportedTypesDef 从程序集的所有PE模块中导出的每个public类型中在这个表中都有一个对应的记录项。
咱小谈CLR的更多相关文章
- DevStore开发人员服务有奖征文:小谈新浪微博开放平台
DevStore开发人员服务有奖征文:小谈新浪微博开放平台 笔者接入新浪微博开发平台也有一段时间了,对整个平台的接入也算比較熟悉,新浪提供了统一的API接口,能够让开发人员更方便的使用API来实现自己 ...
- 再谈CLR查找和加载程序集的方式
原文:再谈CLR查找和加载程序集的方式 这是一个老问题,以前也有朋友写过一些文章介绍,但可能还不是很全面.我也多次被人问到,这里结合案例再次谈谈,希望对大家有所帮助. 本文范例代码可以通过这里下载 h ...
- 小谈Java里的线程
今天,我们来谈一谈Java里的线程. 一.进程与线程的基本概念 大家可能没听过线程这个概念,但是相信,用计算机的朋友都听过进程这个概念.打开电脑的任务管理器,我们就可以看到许多进程.它们主要分为三类, ...
- 小谈Scrum敏捷开发流程
一晃眼,有两年没有写博客了,回顾前两年,各种奔波,各种忙碌,也有不少的收获.从今天开始,我要把这些收获都分享在这里. 其实这两年,对我影响最大的是开发流程.总所周知,一个好的开发流程,对于项目的进行, ...
- iOS 小谈开发者中的个人、组织(公司、企业)账号
苹果对开发者主要分为3类:个人.组织(公司.企业).教育机构.即: 1.个人(Individual) 2.组织(Organizations) 组织类又分为2个小类: (1)公司(Company) (2 ...
- Http与Socket小谈
http与socket是网络编程中最为重要的概念,不管是客户端还是服务端,都是最为重要的部分,以下简述两者的关系和区别(个人见解). Http 定义 基于应用层的超文本传输协议.通常承载于TCP/IP ...
- 小谈 - web模仿手机打电话与正则表达式
昨天遇到了一个很棘手的问题,就是手机端调用web端的页面,如果用编辑器插入的内容页面中有电话的的数据就要变一下格式,让手机端可以实现拨号的功能. 研究了半天就是没一点头绪,但是偶尔看到数据中每一个电话 ...
- 小谈React、React Native、React Web
React有三个东西,React JS 前端Web框架,React Native 移动终端Hybrid框架,React Web是一个源码转换工具(React Native 转 Web,并之所以特别提出 ...
- scales小谈grunt
Grunt是基于Node.js的项目构建工具.它可以自动运行你所设定的任务.Grunt拥有数量庞大的插件,几乎任何你所要做的事情都可以用Grunt实现. 一头野猪映入眼帘,意:咕噜声 中文网站:htt ...
随机推荐
- IE浏览器打开chorme浏览器,如何打开其他浏览器
看到这个标题是否感觉奇怪,为什么要用IE浏览器打开chorme或者火狐浏览器等,这个功能从开发者来说不是一个好的需求,但确实是真实存在的,有用公司的背景历史比较复杂,而且公司有过长期的开发历史,这导致 ...
- .net基础复习之一
一. ADO 与ADO.NET两种数据访问方式区别? 1. ADO与ADO.NET简介ADO与ADO.NET既有相似也有区别,他们都能够编写对数据库服务器中的数据进行访问和操作 ...
- VS代码提示不出现或者提示变成英文或者各种奇葩问题的解决
万能法==>重置 代码提示变成英文的了 打开开发员命令提示 输入:devenv.exe /setup /resetuserdata /resetsettings 重新打开,会和你第一次安装完毕一 ...
- Unity导出的Xcode工程目录
Classes文件夹: Unity Runtime和ObjectC代码 main.mm和AppController.mm:应用程序入口点 iPhone_Profiler.h:定义了启用内部分析器(In ...
- [汇编与C语言关系]3. 变量的存储布局
以下面C程序为例: #include <stdio.h> ; ; ; int c; int main(void) { ; char b[] = "Hello World" ...
- 《JS设计模式笔记》 1,单例模式
<script type="text/javascript"> //单例模式 //1,每次点击都会生成一个新的div var createMask=function ( ...
- 细说gulp
一.概述&安装 Gulp,简而言之,就是前端自动化开发工具,利用它,我们可以提高开发效率. 比如: 1. 压缩js 2. 压缩css 3. 压缩less 4. 压缩图片 等等… 我们完 ...
- Windows Server 2008 R2 WEB服务器配置系列文章索引
最近这段时间趁天翼云1元主机活动,购买了一个1元主机,主要是为了写一些服务器配置的教程. 已经完成如下几篇文章,送给大家. 国内云主机比较 天翼云/阿里云/腾讯云 Windows Server 200 ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
- 用javascript做一个视频播放器
以前我们在网页上播放视频,都是要麻烦flash来实现.看着那一大段的<object>真心觉得累.随着html5的不断普及,现在是时候使用html5提供的video元素来做点正经事了,但是要 ...