《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 : 把需要传递的对象 通过序列化反序列化的方式传递过去(值拷贝) ...
随机推荐
- [LeetCode] Race Car 赛车
Your car starts at position 0 and speed +1 on an infinite number line. (Your car can go into negati ...
- Servlet 过滤器Filter
特点 1)Filter是依赖于Servlet容器,属于Servlet规范的一部分,在Servlet API中定义了三个接口类:Filter, FilterChain, FilterConfig. 2) ...
- 使用ANY和ALL条件
在比较运算符中,可以出现ALL和ANY,表示“全部”和“任一”,但是ALL和ANY不能单独使用,需要配合单行比较操作符>.>=.<.<=一起使用.其中: > ANY : ...
- seed实验——Set-UID Program Vulnerability实验
一.实验描述 Set-UID是Unix OS中的一个·非常重要的安全机制.当一个Set-UID程序运行的时候,它具有代码拥有者的权限.举个例子,如果代码的拥有者是root用户,那么不论任何用户运行该程 ...
- Parallel线程安全问题
废话不多说,上代码: using System; using System.Collections.Generic; using System.Threading.Tasks; namespace P ...
- nginx+letsencrypt搭建https站点
1. 申请好自己的域名 dockerhub.xxx.com,并解析好IP. 2. 安装nginx(默认开通了http) ,修改 server_name dockerhub.xxxx.com; 启动. ...
- [Swift]LeetCode236. 二叉树的最近公共祖先 | Lowest Common Ancestor of a Binary Tree
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree. According ...
- Xcode 命令行工具 Command Line Tools
xcode命令行工具包是一个小型独立包,可供下载独立于Xcode的和允许您执行命令行开发OS X. 在OS X10.9,就以及没有clt的下载安装包了,需要使用命令在线安装. xcode-select ...
- java代码之美(9)---guava之Lists、Maps
guava之Lists.Maps 谷歌提供了guava包里面有很多的工具类,Lists和Maps集合工具,集合操作做了些优化提升. 1.概述 1.静态工厂方法 (1)Guava提供了能够推断范型的静态 ...
- linux-centerOs6.8安装nginx与配置
一:安装nginx 1.安装gcc(命令:yum install gcc)备注:可以输入gcc -v查询版本信息,查看是否自带安装 2.安装pcre(命令:yum install pcre-devel ...