CLR: 那些你不知道你不知道的事情

 

程序集(Assembly)和模块(Managed Module)

 

 

前言

一直都用集成开发坏境(IDE),一直对模块和程序集的概念理解的不是很直观,因为一Build就把你的单个模块塞进程序集里面去了。当然,对你的编程也不会造成太大的影响。但有些东西你最好还是知道比较好,而且对安装部署你的应用程序一定条件下有帮助。

首先我们先来认识下托管模块(Managed Module)。PE头+CLR头+元数据metadata+IL。想必关于这个结构应该不会很陌生。还是费点笔墨介绍一下:

1, PE头,这是标准的window PE头吧,顺序结构的,是否是32位的,是CUI还是GUI的,还是library的等信息。刚写完一段代码利用这里的信息来编码判断文件是基于32还是64的。

2, CLR头呢,自然是CLR要用的,里面有CLR的版本信息,若是可执行程序的话,入口函数main位置信息,还包含了下面将要提到的metadata的位置信息等。

3, Metadata,元数据。这是一个很重要的概念,使得咱们的托管模块有自我描述的能力。这个地方包含的都是咱这个模块里面的元素,类型,方法,变量等,另外如果还有引用别的模块的类似这些信息。这是区别于非托管模块的一个重要点:

  1. Dev10(微软内部的说法,指visual studio 2010)的编码智能提示,你输入一个点或者ctrl+j快捷方式,就能列出所有可用的类型和成员来。该功能就依赖于此;
  2. 咱有对象的序列化和反序列化(XML或者Binary的格式)也需要依赖于元数据对对象结构的描述。WCF的数据契约DataContract,WWF的工作流状态持久化机制,很多。
  3. 元数据里面存了对别的对象的引用,所以可以在运行时再加载需要的对象(通过JIT编译),这使得我们不需要再像其他非托管模块编译的时候需要把其他被引用模块一起编译进来。
  4. 咱重要的垃圾回收机制(GC)的实现也依赖于此,想必大伙都对这机制不会陌生,说是当一个对象没有被再引用的时候会被标志城可回收的,就像清洁工阿姨判断这个物品时别人丢弃的还是暂时存放在地上的,然后清洁工阿姨会根据自己的判断来清理这些东西。但是当一个对象对进行回收处理的时候,该对象引用的其他需要被回收的对象abc也需要被回收掉,这个时候就可以通过咱的元数据去定位abc了。
  5. 等等

4, IL, intermediate language,是介于高级编程语言和计算机指令的中间态指令。如何产生?语言编译器产生,用C#得都熟悉CSC.exe命令,该命令可以把你写的helloword程序转化成IL。如何执行?这就有依赖于前面提到过的JIT编译器了。简单的一句话表达:当代码块别第一次执行的时候会执行实时编译,然后把metadata指向的该方法内存地址替换掉,然后再执行该方法内存空间上的指令,所以第二次执行的就不需要编译了。写到这里,我想到了两个问题,一个是性能问题,另外一个是编译粒度问题。不妨简单的来讨论一下:

性能问题。

把IL编译成计算机指令,当然会有性能消耗,这个好像也是非托管和托管之间争议的最大的地方吧,非托管就直接编译成计算机指令了,就能直接执行了。托管的还需要再被编译一次,虽然这个过程作了优化,也相信微软一直会不断优化这个过程,总归有性能方面的担心,很正常。这种差异肯定是客观存在的,不过下面的一些介绍会些许减少一些你的顾虑吧:

i.      在介绍时候被提到了就是一个代码块只会被编译一次,第二次就直接使用计算机指令了。看到这个你是不是有了一些想法,对的编程是不是起到了一定的作用?想说的是合理的代码结构设计和编程习惯,会让你的代码变快。还不明白的话就举个具体例子,当你要实现像个类似功能,他们80%的逻辑是一样的,试着把公共模块抽离出来做成一个可能只有参数差异的方法供这些功能调用,不管是从维护还是从性能的角度您都提高了你的性能。(当然事情并非那么绝对。为了不误导各位,这里不得不提的是方法内联的编译优化概念。具体的请自己查阅或关注近期更新的博客,篇幅太长不适合阅读)

ii.      第二个想说的是我们可以充分JIT的智能优化,最直观的是最CPU指令的优化,不同类型CPU对处理同一个动作有不同的适合自己的最优化指令,JIT可以做到这个。为什么单独拿出来说这个,因为这个是相对于静态非托管编译的一个很大的优化。哦,你懂了。

iii.      当然你如果还是心存芥蒂的话,其实没关系,在SDK目录下面有一个命令教NGen.exe,对了,可以把IL直接转化成计算机指令,关注以后的博客更新会有提到如何使用以及注意事项。

编译的粒度问题。

对于动态编译执行的代码,选择在何时编译,编译多少相关的代码块,这种时机和粒度的选择是于性能和计算机资源利用效率是至关重要的。(写着写着又篇幅过长了,打算留到后面再作介绍)

认识完托管模块的结构后,再来看看程序集Assembly。

看到这个集,就知道是个集合,程序集,就是很多程序的集合,那程序文件是什么,就是上面我们提到的模块,当然能被称作程序文件的不只是模块啦,还有资源文件类的,图标,本地化语言包等。所以啊,一个或者多个程序文件就构成了我们的程序集。放心,这里介绍的程序集的概念不会太多打破你之前的认识。只是再稍作介绍而已。

当我们用命令行得到一个test.exe的时候,这就是一个程序集,只是是一个单个模块没有资源文件的程序集。

Csc /out:test.exe /t:exe program.cs

这里你想到怎么让一个程序集能有多个模块呢,又怎么能够有包含资源文件呢?咱接着输入命令行:

Csc  /t:module testmodule.cs

你就会得到一个testmodule.netmodule的文件,没见过吧,这就是一个模块文件,你可以同样的方式得到另外一个模块文件然后在用AL.exe把两个模块文件编译进一个程序集mergedAssemly.dll:

Al /out:mergedAssemly.dll /t:library testmodule.netmodule testmodule1.netmodule

这里有几点注意的是:

  • al.exe /t的类型只能是library,想啊,如果是exe或者winexe的话,你都没指定入口函数呢(你也可以用al.exe指定入口函数的用法)。
  • 这里程序集的执行还是依赖于物理的.netmodule文件的,并没有把模块文件内嵌到程序集里面去,这给你了条件可以按需部署你的程序了。
  • Assembly 的metadata里面专门有一个是manifest的区域空间,清单嘛,想想应该也知道是用来包含该程序集里面的程序文件的信息的。
  • 当然csc.exe和al.exe还能做很多事情,不一一举例了,为什么单独build一个模块文件的目的也在于更直观的让大伙体会到两者的关系。
  • 对于CLR来说,是不能直接使用Module的。Assembly是一个重用的单元,有自己的版本和安全信息的保护。

总结

写的过长了,也有些纰漏和不足,欢迎指正。

目的在于自我总结和分享。纯原创,各种非商业目的使用的欢迎。

转载于:https://www.cnblogs.com/ethanwang/archive/2012/05/25/2517749.html

CLR: 那些你不知道你不知道的事情 程序集(Assembly)和模块(Managed Module)相关推荐

  1. c#笔记--程序集(Assembly)、模块(Module)、类型(class)、命名空间、反射

    Assembly   =装配件.表示一个程序集,它是一个可重用.无版本冲突并且可自我描述的公共语言运行时应用程序构建基块.(大概就是一组dll?)   命名空间:System.Reflection   ...

  2. C#程序集Assembly学习随笔(第一版)_AX

    ①什么是程序集? 可以把程序集简单理解为你的.NET项目在编译后生成的*.exe或*.dll文件. 嗯,这个确实简单了些,但我是这么理解的.详细: http://blog.csdn.net/sws83 ...

  3. CLR via C# 3 读书笔记(4):第1章 CLR执行模型 — 1.4 执行程序集代码

    托管程序集中包含元数据和IL.IL是独立于CPU的机器语言,比大多数CPU机器语言都要高级得多.IL可以访问和操作对象类型,包含创建和初始化对象.调用虚方法和直接操作数组元素.抛出和捕获异常的指令.可 ...

  4. C#-获取当前程序集Assembly的文件名

    C#获取当前程序集Assembly的文件名 fly043488 展开 C# Code: string codeBase = Assembly.GetExecutingAssembly().GetNam ...

  5. 你不知道的事情,你的敌人会告诉你

    最近在网上利用闲暇的时间看了点关于企业管理的资料!其中这么一句话让我感慨"你不知道的事情, 你的敌人会告诉你!"是啊!在这么繁杂的社会!企业之间的竞争已经是白热化状态,市场的变化远 ...

  6. 游戏中你不知道的事情

    游戏中你不知道的事情 和平精英的汽车皮肤,兰博基尼.特斯拉.阿斯顿马丁等等,汽车公司与和平精英合作把自己公司的汽车模型植入到游戏当中当做车的皮肤,为汽车公司提升知名度 王者荣耀 赵云的皮肤,赵云的有一 ...

  7. C#程序集Assembly学习随笔(增补版,附图)_AX

    我一直以为我是个人才,今天才TMD知道,我是个天才!  下面的问题一下就弄出来了. 上篇我讲了下我对Assembly的初步认知. 现在来说说怎么使用已有的Assembly. 比如说我在做一个解决方案时 ...

  8. virtual多态 你不知道的事情

    <1>如果父子类虚函数都有默认参数,这种情况下根据指针类型来调用对应函数 <2>构造过程中,虚表还没有建立,此时在构造或析构函数中调用虚函数为静态调用 <3>con ...

  9. GP学习整理(一)—Geoprocessing assembly and Geoprocessor managed assembly

    声明:仅做自己学习整理用,内容拷贝自ArcEngine SDK开发文档 Geoprocessing assembly overview In this topic About the Geoproce ...

最新文章

  1. OpenCASCADE:构建配置文件
  2. Android深度探索--HAL与驱动开发----第十章读书笔记
  3. idea没有git选项
  4. 每个努力奋斗过的人,被不公正的际遇砸了满头包的时候,都有那么一瞬间的代入感。出生就是hard模式的人,早已经历了太多的劳其筋骨饿其体肤,再多的人为考验只会摧毁人对美好的向往。...
  5. 什么样的程序员是最让人讨厌的?朋友们注意了,别做这种人!
  6. android监控方法耗时开源库,【开源完整项目】 AndroidGodEye 监控Android数据指标
  7. 反射 数据类型_c#反射,反射程序员的快乐
  8. docker tar 镜像 容器相互转换
  9. 学习韩顺平java基础笔记 (自用)
  10. 图像处理MATLAB③(Roberts算子边缘检测,膨胀,滤波,腐蚀,开运算,闭运算使用方法)
  11. gridview的sort_asp.net GridView排序简单实现
  12. 发布园友设计的新款博客皮肤BlueSky
  13. Android App 导出APK安装包以及制作App图标讲解及实战(图文解释 简单易懂)
  14. Cocos2D游戏项目CCTableView在Xcode7.2下的无法滚动问题
  15. 21秋期末考试工程项目管理10324k2 (2)
  16. 强制应用横竖屏的简单设置
  17. linux 喂狗时间,看门狗喂狗时间及程序
  18. 健身气功----八段锦
  19. 【HBase】关于包org.apache.hadoop.hbase.client
  20. java canvas 动画效果_八大疯狂HTML5 Canvas及WebGL动画效果

热门文章

  1. Batch Normailzation
  2. C#中采用SHA1或MD5加密字符串的函数
  3. 重构《一》-- 提取方法
  4. oracle关于分区,关于Oracle分区
  5. 超图Cesium鼠标事件处理
  6. raspberry pi_使用Raspberry Pi和pi-hole阻止网络上的广告
  7. iap 审核 文档_为什么必须审核文档
  8. Bootstrap 工具提示插件Tooltip的方法
  9. cmake学习笔记(2)--CMake常用的预定义变量
  10. php绕过验证,PHP-Nuke绕过识别码验证漏洞