1.浅谈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类型中在这个表中都有一个对应的记录项。

时间: 2024-08-03 13:22:09

1.浅谈CLR的相关文章

浅谈CLR

1.什么是CLR CLR(Common Language Runtime)公共语言远行时,是一个可由多种编程语言使用的“远行时”.CLR的核心功能(比如内存管理.程序集加载.安全性.异常处理和线程同步)可由面向CLR的所有语言使用.CLR不关心开发人员使用哪种语言进行编程,只要编译器面向CLR就可以了,所有,开发人员应该使用自己最适合和熟悉的语言进行编程.所有的编程语言在面向CLR编译器的编译都生成了一个托管模块.托管模块是一个标准的32位的Microsoft Windows可移植执行体(PE3

浅谈SQL Server 对于内存的管理

简介 理解SQL Server对于内存的管理是对于SQL Server问题处理和性能调优的基本,本篇文章讲述SQL Server对于内存管理的内存原理. 二级存储(secondary storage) 对于计算机来说,存储体系是分层级的.离CPU越近的地方速度愉快,但容量越小(如图1所示).比如:传统的计算机存储体系结构离CPU由近到远依次是:CPU内的寄存器,一级缓存,二级缓存,内存,硬盘.但同时离CPU越远的存储系统都会比之前的存储系统大一个数量级.比如硬盘通常要比同时代的内存大一个数量级.

浅谈C#中堆和栈的区别(附上图解)

线程堆栈:简称栈 Stack 托管堆: 简称堆 Heap 使用.Net框架开发程序的时候,我们无需关心内存分配问题,因为有GC这个大管家给我们料理一切.如果我们写出如下两段代码: 代码段1: public int AddFive(int pValue) { int result; result = pValue + 5; return result; } 代码段2: public class MyInt { public int MyValue; } public MyInt AddFive(i

浅谈线程池(下):相关试验及注意事项

三个月,整整三个月了,我忽然发现我还有三个月前的一个小系列的文章没有结束,我还欠一个试验!线程池是.NET中的重要组件,几乎所有的异步功能依赖于线程池.之前我们讨论了线程池的作用.独立线程池的存在意义,以及对CLR线程池和IO线程池进行了一定说明.不过这些说明可能有些"抽象",于是我们还是要通过试验来"验证"这些说明.此外,我认为针对某个"猜想"来设计一些试验进行验证是非常重要的能力,如果您这方面的能力略有不足的话,还是尽量加以锻炼并提高吧. C

【转】【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式

ASP.NET MVC系列文章 原文地址:https://www.cnblogs.com/wangjiming/p/6275854.html [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作篇)(下) [04]浅谈ASP.NET框架 [05]浅谈ASP.NET MVC运行过程 [06]浅谈ASP.NET MVC 控制器 [07]浅谈ASP.NET MVC 路由 [08]浅谈AS

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化

浅谈——页面静态化

现在互联网发展越来越迅速,对网站的性能要求越来越高,也就是如何应对高并发量.像12306需要应付上亿人同时来抢票,淘宝双十一--所以,如何提高网站的性能,是做网站都需要考虑的. 首先网站性能优化的方面有很多:1,使用缓存,最传统的一级二级缓存:2,将服务和数据库分开,使用不同的服务器,分工更加明确,效率更加高:3,分布式,提供多台服务器,利用反向代理服务器nginx进行反向代理,将请求分散开来:4,数据库的读写分离,不同的数据库,将读操作和写操作分开,并实时同步即可:5,分布式缓存,使用memc

单页应用SEO浅谈

单页应用SEO浅谈 前言 单页应用(Single Page Application)越来越受web开发者欢迎,单页应用的体验可以模拟原生应用,一次开发,多端兼容.单页应用并不是一个全新发明的技术,而是随着互联网的发展,满足用户体验的一种综合技术. SEO 一直以来,搜索引擎优化(SEO)是开发者容易忽略的部分.SEO是针对搜索(Google.百度.雅虎搜索等)在技术细节上的优化,例如语义.搜索关键词与内容相关性.收录量.搜索排名等.SEO也是同行.市场竞争常用的的营销手段.Google.百度的搜

浅谈html标签

浅谈html各常用标签用法 标题标签:<h1>-<h6>来表示,使标题字体变粗. <br />换行标记 <hr />水平分隔符 &nbsp空格符 &copy版权符 <a href>a标签超链接 href可接链接地址 <p>段落标签<blockquote>引用标签及可用做缩进 <table>表格中的<ul>无序列表<ol>有序列表<dl>自定义列表<row