理解.NET程序集的执行过程

  对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.NET 程序集是包含复杂结构的MSIL代码,执行时会使用JIT即时编译器将IL代码编译成机器码,再由CPU执行,当然这期间还需要执行其它许多的工作,如加载CLR、执行初始化等工作,那么这些是怎么自动实现的呢?

  理解这些问题是我们深入.NET的关键,由于日常的开发工作并不涉及这些知识(编译器已经给我们做了),结果是很多的.NET 书忽略了这一点,也很少有人研究者方面的内容,所以在阅读了《.NET 高级调试》这本书给了我非常清晰地认识,把里面的这方面精彩的内容做了一个总结以供那些还没有清楚.NET 程序集如何执行的学者们一个简单的参考。

  首先我们要清楚的是对于托管还是非托管程序集,他们在编译器执行编译时都会编译成一个特殊的文件格式,即PE文件(可移植可执行文件格式),操作系统加载器通过加载这样的PE文件来执行程序集的。可以这么说吧,无论是托管程序还是非托管程序他们实际上都是编译成这样的PE文件(只是有部分内容不一样而已)。

  然后这个PE文件会指示如何执行托管程序集和非托管程序集,加载器首先会查找到PE头中的AddressOfEntryPoint域,这个域指示PE文件的入口点位置,在.NET程序集中是指向.text段中的CLR头--〉包含一个结构IMAGE_COR20_HEADER—包含许多信息如托管代码应用程序的入口点,目标CLR的主版本号和从版本号,以及程序集的强名称签名等--〉Windows加载器根据这个数据结构决定加载哪个版本的CLR以及一些基本的程序集信息。在.text段中还包含了程序集的元数据表,MSIL以及非托管启动存根代码,而非托管启动存根代码包好了由Windows加载器执行役启动PE文件执行的代码,结构如图所示。

  这样.NET 程序集的加载算法包括:

  1、用户执行一个.NET程序集;

  2、Windows加载器查看AddressOfEntryPoint域,并找到PE映像文件的.text段;

  3、位于AddressOfEntryPoint位置上的字节只是一个JMP(跳转)指令,这个指令跳转到mscoree.dll中的一个导入函数;

  4、将执行控制转移到mscoree.dll中的_CorExeMain中,这个函数将启动CLR并把执行控制转移到程序集的入口点。

时间: 2024-10-14 18:00:03

理解.NET程序集的执行过程的相关文章

一起谈.NET技术,理解.NET程序集的执行过程

对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.NET 程序集是包含复杂结构的MSIL代码,执行时会使用JIT即时编译器将IL代码编译成机器码,再由CPU执行,当然这期间还需要执行其它许多的工作,如加载CLR.

“.NET研究”理解.NET程序集的执行过程

对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成上海企业网站制作以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.NET 程序集是包含复杂结构的MSIL代码,执行时会使用JIT即时编译器将IL代码编译成机器码,再由CPU执行,当然这期间还需要执行其它许多的工作

理解“.NET技术”.NET程序集的执行过程

对于一个已编译好的.NET程序集,Windows操作系统是如何启动执行的呢?日常使用中我们发现对于托管的和非托管的程序集编译器都会吧程序集编译成以.exe或.dll等为扩展名的文件,可见Windows加载器并没有区分是托管还是非托管的程序集,而且我们也知道对非托管的程序集是在编译器直接编译成了机器码,自然可以由CPU直接执行,而托管的.NET 程序集是包含复杂结构的MSIL代码,执行时会使用JIT即时编译器将IL代码编译成机器码,再由CPU执行,当然这期间还需要执行其它许多的工作,如加载CLR.

jvm执行流程(static代码块和初始化快和父类子类执行过程)

大家猜想一下,结果会是什么? 为什么会是这样呢? 1.jvm加载StaticBlock的main方法前,要看SubClass中是否有静态的变量和语句,如果有,先给这些静态的变量分配存储空间和执行静态语句(不是静态方法),且由于SubClass的父类中也有静态的变量,根据继承的特性,则先执行父类Parent的静态数据的初始化,然会执行子类的静态数据的初始化. 2.执行main方法中的new StaticBlock(); 语句,进行Parent的类的实例化因为Parent的静态数据已经实例化,并且在

Javascript的执行过程简介

正如我们了解的一样,当我们书写了JS程序之后,打开浏览器,我们的代码就可以开始运行了(当然保证你的代码没有问题,才能按照你的预期进行执行).刚才说的是JS执行的一个大的环境,今天我们学习一下,JS在解析器里的一个执行过程. 这个过程分为两个阶段: 进入执行上下文执行代码    变量对象的变化,和这两个阶段息息相关. 在介绍这两个阶段之前,了解相关的概念. 如果变量和执行上下文相关,那么它应该知道在哪里存储数据和怎么访问数据,这种机制叫做变量对象(variable object,简称VO).用于存

从底层简析Python程序的执行过程

  这篇文章主要介绍了从底层简析Python程序的执行过程,包括注入操作码和封装程序等解释器执行层面的知识,需要的朋友可以参考下 最近我在学习 Python 的运行模型.我对 Python 的一些内部机制很是好奇,比如 Python 是怎么实现类似 YIELDVALUE.YIELDFROM 这样的操作码的;对于 递推式构造列表(List Comprehensions).生成器表达式(generator expressions)以及其他一些有趣的 Python 特性是怎么编译的;从字节码的层面来看

操作系统-有谁能详细介绍一下,环境变量中path路径的执行过程吗?

问题描述 有谁能详细介绍一下,环境变量中path路径的执行过程吗? 就是假设我将环境变量中的path改为了 path=%JAVA_HOME%;bin; 那当我调用java程序进行编译时, 操作系统是通过怎样的路径来寻找 jvm..cfg的呢? ps:我不知道为什么,当我这里写相对路径,如以上的时候: 报一下的错误: 那当我改为绝对路径时,就会正常运行,如一下: 求解,谢谢 解决方案 先在环境变量里定义JAVA HOME,然后在path 里引用 解决方案二: Java_home我定义过了得 解决方

第10周-任务0-构造和析构函数的执行过程实例解析

[题目]阅读程序,先分析程序的执行结果,在上机时运行程序进行对照,再通过单步执行跟踪程序的运行,达到理解基类.派生类中构造函数.析构函数执行过程的目的. 程序如下: #include <iostream> using namespace std; class Part  //部件类 { public:     Part();     Part(int i);     ~Part();  private:     int val; }; class Whole: public Part { pu

从底层简析Python程序的执行过程_Mysql

最近我在学习 Python 的运行模型.我对 Python 的一些内部机制很是好奇,比如 Python 是怎么实现类似 YIELDVALUE.YIELDFROM 这样的操作码的:对于 递推式构造列表(List Comprehensions).生成器表达式(generator expressions)以及其他一些有趣的 Python 特性是怎么编译的:从字节码的层面来看,当异常抛出的时候都发生了什么事情.翻阅 CPython 的代码对于解答这些问题当然是很有帮助的,但我仍然觉得以这样的方式来做的话