在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
源代码——》托管模块——》程序集—JIT—》编程CPU指令 1.1 在.NET框架下,首先将源代码编译为托管模块CLR编译过程:C#源码文件——(C#编译器编译)——》托管模块
托管模块是一个需要CLR环境才能执行的标准windows PE文件,包含IL和元数据以及PE表头和CLR表头。 iL: 又叫托管代码,是编译器编译原文件后产生的指令,CLR会在运行时将IL编译成本地CPU指令。 元数据实际上是一个数据表集合,用来描述托管模块中所定义和引用的内容。VS能够智能感知就得益于元数据的描述 内容: 1.描述了模块中定义的内容,比如类及其成员 用途: 1.消除了对头/库文件的依赖,直接从托管模块中读取 PE表头:标准Windows PE文件表头,包含文件类型(如GUI、CUI等),以及文件创建时间等信息,在32位还是64位上运行 CLR表头:包含标识托管模块的一些信息。如CLR版本号,托管模块入口点方法(main方法)以及MethodDef元数据等等 1.2托管模块组合为程序集程序集:一个或多个托管模块/资源文件的逻辑分组,是最小的重用,安全性以及版本控制单元。 一般编译器会默认将生成的托管模块生成一个程序集,CLR直接打交道的是程序集(assembly),程序集包含一个或多个托管模块,以及资源文件的逻辑组合。组合过程如下: 左侧为一些托管模块,在经过一些工具的处理后,生成了一个PE文件,也就是程序集。程序集中有一个清单(manifest)数据块,用来描述组成程序集的所有文件。此外,程序集还包含它所引用的程序集的信息,这就使得程序集可以实现自描述。这样CLR就直接知道了程序集所需要的所有内容,因此程序集的部署比非托管组件要容易。 1.2 加载 CLR CLRVer命令,查看机器上所有CLR版本 程序要运行,首先确定及其安装了.NET框架.然后,加载并初始化CLR 1.4 程序集执行(ILAsm命令,将IL编译成Assembly;ILDasm将Assembly编译成IL) IL代码要通过及时编译器JITter转化成CPU指令 方法第一次调用: ( 在方法首次执行时,CLR检测出Main的代码引用的所有类型,于是CLR分配一个内部数据结构,用于管理对引用类型的访问 在这个内部结构中,每个方法都有一条对应的纪录以及地址 对此结构进行初始化时,CLR将每条纪录都设置为CLR内部包含的一个未文档化的函数,即 JITCompiler函数。 ) 1. 当程序第一次运行时,会调用JITCompiler函数,它可以知道调用了那些方法,以及定义该方法的类。 2. 然后JITCompiler函数在元数据中搜索该IL代码的位置,验证后转换成本地CPU指令。将指令保存在动态分配的内存中 3. JITCompiler将被调用方法地址改为第2步的内存地址 4. 跳转到上述代码块上执行代码 5. 执行完成后返回 IL是基于堆栈的语言,而且是无类型的。 再次调用方法 在一个程序中,我们经常反复调用同一个方法,当再次调用该方法时就不需要重复进行验证了,可以直接调用内存块中已有的本地代码,完全跳过JITCompile函数的验证和编译过程。所以同一方法只有在第一次调用时会产生一些性能损失,后续调用就可以全速进行了。 关闭程序 由于编译器将本地代码保存在动态内存中,所以关闭程序时本地代码将发生丢失。当再次启动程序或者同时运行程序的两个实例时,JIT编译器将再次将IL代码编译为本地指令。 谈谈IL安全问题
|
请发表评论