CLR 托管模块介绍

2024-02-15 11:58
文章标签 模块 介绍 托管 clr

本文主要是介绍CLR 托管模块介绍,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 托管模块(中间语言和元数据)是一个标准的32位Microsoft Windows可移植执行体(PE32)文件,或者是一个标准的64位Windows可移植执行体(PE32+)文件,他们需要CLR才能执行。

 

本地代码编译器生成的是一种特定的CPU架构(比如X86,X64或者IA64)专用的代码。相反所有CLR相容的编译器生成的都是

“中间语言(Intermediate language ,IL)”IL代码也称为托管代码,因为CLR会管理它的执行。

 

除了生成IL,面向CLR的每个编译器还需要在每个托管模块中生成完整的元数据。简而言之,元数(metadata)是一系列特殊的数据表,他们描述了描述了模块中定义的内容,比如类型及其成员。除此之外,还有一些元数据表指出了托管模块引用的内容,比如导入的类型及其成员。元数据是一些老技术的超级。这些老技术包括“类型库(Type Library)”和“接口定义语言Interface Definition language,IDL”文件等。要注意的一个重点在于,CLR元数据比他们完整得多。另外,和类型库及IDL不同,元数据总是与包含IL代码的文件关联在一起。事实上,元数据总是嵌入与代码相同的EXE/DLL,这使两者密不可分。由于编译器同时生成元数据和代码,并将他们绑定到最终生成的托管模块中,所以元数据及其描述的IL代码永远不会失去同步。

 

 

托管模块的组成:PE32或PE32+头,CLR头,元数据,中间语言IL代码

 

 

托管相较于非托管代码的优势:

JIT编译器能判断应用程序是否运行在一个INTER Pentium4 CPU上,并生成相应的本地代码来利用P4支持的任何特殊指令。通常,非托管应用程序是针对具有最小功能集合的CPU编译的,不会使用可提升应用程序性能的特殊指令,等等。

 

 

 

 

 

 

-----------------------------------------------------------------------JIT即使编译器-----------------------------------------------------------------------------

 

 

为了执行一个方法,它的IL首先必须转换成本地的CPU指令。这是CLR的JIT(just-in-time或者“即时”)编译器的职责。

 

就在Main方法执行之前,CLR会检测出Main的代码引用的所有类型,这导致CLR分配一个内部数据结构,它用于管理对引用类型的访问。Main方法引用了单一类型Console,造成CLR分配单独一个内部结构。在这个内部数据结构,Console类型定义的每个方法都有一条对应的记录。每条记录都容纳了一个地址,根据此地址即可找到方法的实现。对这个结构进行初始化时,CLR将每条记录都设置成CLR内部包含的一个未文档化的函数。我将这个函数称为JITCompiler。

 

Main方法首次调用WriteLine时,会调用JITCompiler函数。JITCompiler函数负责将一个方法的IL代码编译成本地CPU指令。由于IL是“即时”编译的,所以通常将CLR的这个组件称为JITter或者JIT编译器。

 

 

JITCompiler函数被调用时,它知道要调用哪个方法,以及具体是什么类型定义了该方法。然后,JITCompiler会在定义程序集的元数据中搜索被调用的方法IL。JITCompiler接着要验证IL代码,并将IL代码编译成本地CPU指令。本地CPU指令保存在一个动态分配的内存块中。然后JITCompiler回到CLR为类型创建的内部数据结构,找到与被调用的方法对应的那一条记录,然后将最初调用它的那个引用替换成内存块(其中包含刚才编译好的本地CPU指令)的地址。最后,JITCompiler函数会跳转到内存块中的代码。这些代码正是WriteLine方法(获取单个string参数的那个版本)的具体实现。代码返回时,会返回到Main中的代码,并继续执行。

 

现在,Main要第二次调用WriteLine。这一次,由于已对WriteLine的代码进行了验证和编译,所以会直接执行内存块中的代码,完全跳过JITCompiler函数。WriteLine方法执行完毕后,会再次返回Main。

 

一个方法只有在首次调用的时候才会造成一定的性能损失。以后对该方法的所有调用都以本地代码的形式全速的运行,因为不需要再次执行验证和编译成本地代码。

 

 

JIT编译器将本地CPU指令保存在动态内存中。一旦应用程序终止,编译好的代码也会被丢弃。所以将来再次运行应用程序,或者同时启动了应用程序的两个实例(在两个不同的操作系统进程中),JIT编译器必须再次将IL编译成本地指令。

这篇关于CLR 托管模块介绍的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/711326

相关文章

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

MySQL中慢SQL优化的不同方式介绍

《MySQL中慢SQL优化的不同方式介绍》慢SQL的优化,主要从两个方面考虑,SQL语句本身的优化,以及数据库设计的优化,下面小编就来给大家介绍一下有哪些方式可以优化慢SQL吧... 目录避免不必要的列分页优化索引优化JOIN 的优化排序优化UNION 优化慢 SQL 的优化,主要从两个方面考虑,SQL 语

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

Python实现html转png的完美方案介绍

《Python实现html转png的完美方案介绍》这篇文章主要为大家详细介绍了如何使用Python实现html转png功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 1.增强稳定性与错误处理建议使用三层异常捕获结构:try: with sync_playwright(

Java使用多线程处理未知任务数的方案介绍

《Java使用多线程处理未知任务数的方案介绍》这篇文章主要为大家详细介绍了Java如何使用多线程实现处理未知任务数,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 知道任务个数,你可以定义好线程数规则,生成线程数去跑代码说明:1.虚拟线程池:使用 Executors.newVir

python中time模块的常用方法及应用详解

《python中time模块的常用方法及应用详解》在Python开发中,时间处理是绕不开的刚需场景,从性能计时到定时任务,从日志记录到数据同步,时间模块始终是开发者最得力的工具之一,本文将通过真实案例... 目录一、时间基石:time.time()典型场景:程序性能分析进阶技巧:结合上下文管理器实现自动计时

JAVA SE包装类和泛型详细介绍及说明方法

《JAVASE包装类和泛型详细介绍及说明方法》:本文主要介绍JAVASE包装类和泛型的相关资料,包括基本数据类型与包装类的对应关系,以及装箱和拆箱的概念,并重点讲解了自动装箱和自动拆箱的机制,文... 目录1. 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱2. 泛型2

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.