《CLR via C#》读书笔记(一)——CLR的执行模式
前言
万事开头难,很早之前就想写博客记录些东西,迟迟未行动,甚是遗憾。原因诸多,大体上无非都是懒、没意志力等等。这次从自己的读书笔记开始,兴许能够有所改变。
一、CLR概念
CLR(Common Language Runtime,译为公共语言运行时)是一个可由多种编程语言使用的“运行时”。CLR的核心功能:内存管理、程序集加载、安全性、异常处理和线程同步,可由面向CLR的所有语言(C++、C#、VB、F#等等)使用。无论哪种语言,最后通过编译器的结果都是托管模块。托管模块是PE32文件或PE32+文件,都需要CLR才能执行。
组成部分 | 说明 |
PE32或PE32+头 | 标准windows PE文件头,如果这个头是PE32格式,文件能在Windows32位和64位上运行,如果是PE64,文件只能在Windows的64位上运行。这个头还表示了文件类型,,并包含一个时间标记来指出文件的生成时间。对于只包含IL代码的模块,这些信息大部分都会被忽略。如果是包含本机CPU代码的模块,这个头包含本机CPU代码有关的信息。 |
CLR头 | 包含使这个模块成为托管模块的信息。头中包含要求的CLR版本,一些标志(flag),拖过模块入口方法的元数据token以及模块的元数据、资源,强模块、一些标志以及不太重要的数据项位置/大小 |
元数据 |
每个托管模块都包含元数据表。分为两类: 1、描述源代码中定义的类型和成员。 2、描述源代码引用的类型和成员。 元数据有诸多用途,例如: 1、元数据表面了编译时对原生C/C++和库文件的需求,因为在实现类型/成员的IL代码文件中,已包含有关引用类型/成员的全部信息。编译器直接从托管模块中读取元数据。 2、IDE的“智能感知”能够解析元数据,从而得到一个类型所提供的方法、属性、事件和字段。 3、CLR的代码验证过程使用元数据确保代码只执行“类型安全”的操作 4、元数据允许将对象的字段序列化到内存,将其发送给另一台机器,然后反序列化,在远程机器上重建对象状态 5、元数据允许垃圾回收器跟踪对象生存期,垃圾回收器能判断任何对象的类型并从元数据知道那个对象中的哪些字段引用了其他对象 |
IL代码 | IL代码也被为托管代码,因为CLR管理它到底执行。编译器编译源代码时生成的代码。在运行,CLR将IL编译成本机CPU指令 |
二、程序集执行过程
IL代码是与CPU无关的机器语言,当方法执行时,必须把方法的IL转换成本机CPU命令。下图是方法的首次调用
在执行Main方法前,CLR会分配一个内部数据结构来管理对引用类型的访问,在这个内部数据结构项中,存在与类型中方法对应的一个记录项,这个记录项含有一个地址,可根据此地址找到方法的具体实现。数据结构初始化时,CLR将每个记录项都设置成包含在CLR内部的JITComplier。上图中的WriteLien首次调用时,JITCompiler会被调用,IL将被编译成CPU指令(JIT,即时编译)。当WriteLine第二次调用时,会跳过JITCompiler,直接执行CPU中已有的指令。(注:之前有经常遇到过首次调用某类方法明显比第二次的耗时长,应该与此有关联,因此有时候需要做预加热)。 下图为第二次调用
生成程序集时,有两种模式:Debug和Release。显然,根据词义可知分别是调试模式和发布模式。两者主要区别在于两个C#编译器开关会影响代码优化:/optimize和/debug。Debug含有DEBUG常量,以及不优化代码。Release不包含DEBUG常量,并优化代码。因此Release模式下的程序集相对而言更小,运行更快。
尽管微软做了大量的工作来优化,但运行时的二次编译仍会影响性能,也会分配动态内存。但是.NET FrameWork SDK 配套提供了NGen.exe工具,该工具将所有IL代码编译成本机代码,并将这些本机代码保存到了一个磁盘文件中。NGen.exe能够:1、提高应用程序的启动速度;2、减小应用程序的工作集。纵然NGen.exe工具能够带来不少好处,却并非那么完美,存在如下问题:1、没有知识产权保护 2、NGen生成的文件可能失去同步 3、交叉的执行时性能。因此,在使用NGen.exe工具时要慎重考虑,除非是启动耗时的大型客户端应用程序。
三、Framework类库
.Net Framework包含Framework类库(Framework Class Library,FCL)。FCL是一组DLL程序集的同城,其中包含有数千个类型定义。例如:WEB服务、基于HTML的web窗体/MVC应用程序、“富”WIndows GUI应用程序,Windows控制台应用程序,Windows服务,数据库存储过程,组件库等
四、通用类型系统和公共语言规范
为了令一种编程语言写的代码能与用另一种编程语言写的代码沟通,微软制定了一个正式的规范来描述类型的定义和行为,这既是“通用类型系统”(Common Type System,CTS)。CTS规定,一个类型可以包含零个以上的成员:字段、方法、属性、事件,CTS还指定类型可见性规则以及类型成员的额访问规则:private、family(protected,派生类型访问)、assembly(同一个程序可访问)、public。同时,CTS规定所有类型必须继承System.Object。CTS还有其他规则,不一一列出。
微软定义了“公共语言规范”(Common Language Specification,CLS),详细定义了一个最小功能集,用于不同语言创建的对象可通过COM相互通信,任何支持CLR的编译器都支持这个功能集。
注:程序集执行过程图来源自网络
《CLR via C#》读书笔记(一)——CLR的执行模式的更多相关文章
- CLR via C# 读书笔记-21.托管堆和垃圾回收
前言 近段时间工作需要用到了这块知识,遂加急补了一下基础,CLR中这一章节反复看了好多遍,得知一二,便记录下来,给自己做一个学习记录,也希望不对地方能够得到补充指点. 1,.托管代码和非托管代码的区别 ...
- 《Head First 设计模式》读书笔记(1) - 策略模式
<Head First 设计模式>(点击查看详情) 1.写在前面的话 之前在列书单的时候,看网友对于设计模式的推荐里说,设计模式的书类别都大同小异,于是自己就选择了Head First系列 ...
- CLR via C# 读书笔记---常量、字段、方法和参数
常量 常量是值从不变化的符号.定义常量符号时,它的值必须能在编译时确定.确定后,编译器将唱两只保存在程序集元数据中.使用const关键字声明常量.由于常量值从不变化,所以常量总是被视为类型定义的一部分 ...
- Clr Via C#读书笔记---I/O限制的异步操作
widows如何执行I/O操作 构造调用一个FileStream对象打开一个磁盘文件-----FileStream.Read方法从文件中读取数据(此时线程从托管代码转为本地/用户模式代码)- ...
- Clr Via C#读书笔记---计算限制的异步操作
线程池基础 1,线程的创建和销毁是一个昂贵的操作,线程调度以及上下文切换耗费时间和内存资源. 2,线程池是一个线程集合,供应你的用程序使用. 3,每个CLR有一个自己的线程池,线程池由CLR控制的所有 ...
- Clr Via C#读书笔记---CLR寄宿和应用程序域
#1 CLR寄宿: 开发CLR时,Microsoft实际是将他实现成包含在一个dll中的COM服务器.Microsoft为CLR定义了一个标准的COM接口,并为该接口和COM服务器分配了GUID.安装 ...
- Clr Via C#读书笔记---程序集的加载和反射
#1 加载程序集 Assembly.Load: public class Assembly { public static Assembly Load(AssemblyName assemblyRef ...
- Clr Via C#读书笔记---垃圾回收机制
#1 垃圾回收平台的基本工作原理: 访问一个资源所需的具体步骤: 1)调用IL指令newobj,为代表资源的类型分配内存.在C#中使用new操作符,编译器就会自动生成该指令.2)初始化内存,设置资源的 ...
- Clr Via C#读书笔记---线程基础
趣闻:我是一个线程:http://kb.cnblogs.com/page/542462/ 进程与线程 进程:应用程序的一个实例使用的资源的集合.每个进程都被赋予了一个虚拟地址空间. 线程:对CPU进行 ...
- CLR via C# 读书笔记 6-2 不同AppDomain之间的通信 z
跨AppDomain通信有两种方式 1.Marshal By reference : 传递引用 2.Marshal By Value : 把需要传递的对象 通过序列化反序列化的方式传递过去(值拷贝) ...
随机推荐
- 转 the best for wcf client
原文:http://stackoverflow.com/questions/573872/what-is-the-best-workaround-for-the-wcf-client-using-bl ...
- C# 对串口的操作
初始化 串口 SerialPort sp = new SerialPort(); sp.PortName = BasicParameters.IniReadValue(strPath, "C ...
- java课程之团队开发冲刺阶段1.1
一.今天所要完成的内容 1.实现软件添加日期的功能并生成当前所在周的功能 2.对之前的代码进行重新排版,将主函数的内容移到方法中 3.利用Android自带的左侧菜单栏实现app的整体美观
- SQL插入数据--数据中的某一列来自本表中的数据
背景: 项目初期使用的配置库和业务库两种数据库并行,所有配置数据位于配置库,所有业务数据根据不同省份位于不同数据库.由于使用省份越来越多,各省的配置数据也越来越多导致配置库的数据量过于庞大,各省共用一 ...
- idea远程打断点
(1)用如下方式启动jar java -Xdebug -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y -jar durati ...
- #Java学习之路——基础阶段(第四篇)
我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...
- [Swift]LeetCode641. 设计循环双端队列 | Design Circular Deque
Design your implementation of the circular double-ended queue (deque). Your implementation should su ...
- [Swift]LeetCode888. 公平的糖果交换 | Fair Candy Swap
Alice and Bob have candy bars of different sizes: A[i] is the size of the i-th bar of candy that Ali ...
- Saiku设置展示table数据不隐藏空的行数据信息(二十六)
Saiku设置展示table数据不隐藏空的行数据信息 saiku有个 非空的字段 按钮,点击这个后,会自动的把空的行数据信息给隐藏掉,这里我们来设置一下让其行数据不隐藏,为空的就为空. 主要更改两个文 ...
- Kubernetes因限制内存配置引发的错误
今天对一个pod进行内存资源调整后, 一直卡在ContainerCreating的状态, 执行describe命令查看该 Pod 详细信息后发现如下 . [root@master-01 ~]# kub ...