读书笔记—CLR via C#章节1-2

这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享。

程序集

  • 描述:一个或多个类型定义文件及资源文件的集合
  • 特征:可重用、可保护、可版本控制的单元
  • 生成:可通过C#编译器(或其他编译器)或AL.exe生成
  • 组成:
    • 托管模块(module)
      • PE头,PE32或PE32+,面向CPU架构的信息
      • CLR头,面向CLR的信息,版本、入口、元数据等
      • 元数据,源代码类型成员定义和引用的类型成员定义
      • IL代码,编译器生成的托管代码,面向对象的机器语言
    • 资源文件
    • 程序集清单

CPU架构

针对x86、x64和IA64三种平台有三个版本的CLR,信息包含在PE头中

  • 跨CPU架构:使用anycpu,兼容所有CPU架构平台
  • 指定CPU架构:与非托管交互时,考虑到非托管接口的平台特定性,才使用特定CPU架构
/开关 托管模块 x86 windows x64 windows IA64 windows
anycpu PE32/不指定 32位 64位 64位
x86 PE32/x86 32位 Wow64运行 Wow64运行
x64 PE32+/x64 不运行 64位 不运行
Itanium PE32+/Itanium 不运行 不运行 64位

元数据

  • 编译时支持,已包含和引用的类型/成员有关的全部信息
  • 智能感知(Intelligence),成员(方法、属性、事件和字段)及方法参数
  • 验证类型安全
  • 反射和序列化(对象激活与对象重建)
  • 垃圾回收,垃圾收集器能判断对象类型以及对象字段的引用信息

执行流程

  1. 判断是否存在已编译的本地代码,如果存在直接执行(3),否则开启JIT编译器
  2. 启动JIT编译(MSCorEE.dll)
    1. 在元数据中查找调用信息(方法等)
    2. 获取该调用信息的IL
    3. 分配内存块DynamicMemory
    4. 编译IL为本地CPU指令,并存储到DynamicMemory
    5. 修改Type表调用指针指向DynamicMemory
    6. 跳转到DynamicMemory中的本地代码
  3. 执行本地代码(CPU指令)

编译过程

有两个C#编译器开关会影响代码的优化:/optimize和/debug,请看下表:

编译器开关设置 C# IL代码质量 JIT本地代码质量
/optimize- /debug(默认) 未优化 有优化
/optimize- /debug(+/full/pdbonly 未优化 未优化
/optimize+/debug(-/+/full/pdbonly 有优化 有优化

优缺点比较:

  • 未优化(/optimize-),未优化IL代码,包含许多NOP(no-operation)指令,还包含分支指令,优点是即使调试
  • 优化的IL代码,编译器删除多余的NOP和分支指令,代码更小,但却难以单步调试

编译器默认调试配置

    • Debug: /optimize- /debug:full
    • Release: /optimize+ /debug:pdbonly

性能神器 – JIT

  • 将IL编译为本地代码时,对环境的理解比其他编译器更加深刻
  • 生成面向特定CPU的指令,有效利用不同平台的资源提高效率
  • 优化代码,使IL更加轻量,并且更容易理解

鸡肋?NGen.exe

优点:

  • 预编译保存在磁盘上,加快启动速度
  • 减小工作集,进程之间共享代码(通过内存映射)

缺点:

  • 对代码无优化
  • 较差的执行时性能(无特定CPU指令优化,运行时字段无法直接访问)

部署

  私有部署 全局部署
弱命名程序集 支持 不支持
强命名程序集 支持 支持

私有程序集部署特征:引用程序集存放在基目录或者基目录的子目录

探测范围:基路径 - 配置路径 - 相同名称子路径 - 语言文化子目录

私有程序集目录配置:

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="AuxFiles1,AuxFiles2" />
    </assemblyBinding>
  </runtime>
</configuration>

其他(Other Tips)

SDK工具

  • IL编译及反编译 – ILAsm.exe/ILDasm.exe
  • CLRVer.exe 查看CLR版本
  • DumpBin.exe和CorFlags.exe,查看托管模块所嵌入的信息
  • 安全检查工具:PEVerify.exe

IL是中间语言,支持混合编程,C#只是利用CLR的一个子集,IL则是完全面向CLR的

CLR启动入口(MSCorEE.dll)(3种CPU架构3个版本,负责加载程序集)

WoW64能模拟x86指令集

CLS语言规范,规范混合语言之间的互操作 [assembly: CLSCompliant(true)]

语言互操作

  • 托管代码调用dll中的非托管函数(PInvoke平台调用)
  • 托管代码使用现有的COM组件
  • 非托管代码使用托管类型
  • 开源实现:http://CLRInterop.CodePlex.com

响应文件,rsp文件,包含一些编译开关参数,系统全局响应文件自动引用默认程序集

程序集搜索目录及顺序

  1. 工作目录
  2. CSC.exe本身目录
  3. /lib 指定的目录
  4. LIB环境变量指定的目录

多文件程序集,编译器将module合并,addmodule开关,也可以使用AL.exe,用处:

  1. 单独文件存储类型,允许增量更新,分批打包/部署
  2. 嵌入资源
  3. 不同的语言进行实现,然后再合并

程序集文化

  • 语言文化包括特定文化或者文化中性
  • 附属程序集,使用System.Resources.ResourceManager访问附属程序集的资源
  • 设置方式   1:AL.exe /culture    2:[assembly:AssemblyCulture(“de-CH”)]
时间: 2024-12-20 01:16:05

读书笔记—CLR via C#章节1-2的相关文章

读书笔记—CLR via C#章节3

这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享. 强命名程序集 优点 程序集共享 版本共存,解决DLL hell 安全策略(防篡改) 发布策略控制 标识组成 文件名(不计扩展名)+版本号+语言文化+公钥 CLR加载方式 弱命名程序集私有部署,CLR在基目录或子目录中搜索时只使用程序集名称 CLR搜

读书笔记—CLR via C#章节11-13

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 事件 事件的本质 初始化为null的私有委托字段 封装add_Event和remove_Event方法 add_Event和remove_Event的可访问性同Event字段的可访问性,包括virtual和static修饰 事件的编码建议 使用

读书笔记—CLR via C#章节8-10

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 构造函数 抽象类默认的构造函数可访问为protected,普通类默认为public 派生类默认调用一个基类构造器(如果没有无参构造器,则需要显式调用) 不通过构造函数创建对象? 静态方法Object.MemberwiseClone,分配内存复制

读书笔记—CLR via C#章节4-7

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 对象的祖先 – Object 公共方法 Equals, 虚方法,对象相等性,默认调用RuntimeHelpers.Equals方法 GetHashCode,虚方法,返回哈希吗(随机分布的整数),在哈希表中作为键使用 ToString , 默认返

读书笔记—CLR via C#线程27章节

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 同步IO执行过程,拿Read举例 托管代码转变为本地用户模式代码,Read在内部调用Win32的ReadFile函数 ReadFile分配IRP(IO Request Packet) IRP包括:一个文件句柄.文件偏移量.Byte[]数组 IO

读书笔记—CLR via C#同步构造28-29章节

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 类库和线程安全 在类设计中,类和方法的线程安全的设计尽量和FCL保持一致 保证所有的静态方法都是线程安全的 不保证实例方法是线程安全的 基元用户模式和基元内核模式构造 用户模式构造 易失构造(volatile construct),它包含一个简

读书笔记—CLR via C#线程25-26章节

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 线程 线程内部组成 线程内核对象 thread kernel object,在该结构中,包含一组对线程进行描述的属性.数据结构中还包括所谓的线程上下文thread context.上下文是一个内存块,包含了CPU的寄存器集合,占用几百到几千个字

读书笔记—CLR via C#反射

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 程序集加载 AppDomain.Load 尽量避免使用此方法加载程序集,因为Assembly不是从System.MarshalByRefObject派生,所以程序集对象必须按值封送回发出调用的那个AppDomain,但是CLR会使用发出调用的那

读书笔记—CLR via C#委托和attribute

前言 这本书这几年零零散散读过两三遍了,作为经典书籍,应该重复读反复读,既然我现在开始写博了,我也准备把以前觉得经典的好书重读细读一遍,并且将笔记整理到博客中,好记性不如烂笔头,同时也在写的过程中也可以加深自己理解的深度,当然同时也和技术社区的朋友们共享 委托 类型安全的回调函数,函数签名定义声明.指向静态或实例方法 派生自System.MulticastDelegate的类 将方法绑定到委托时,C#和CLR都允许引用类型的协变性和逆变性 协变性指方法能返回从委托的返回类型派生的类型 逆变性是指