《.NET框架程序设计》读书笔记一--.NET程序的生成以及执行过程

.NET程序的生成以及执行过程:
 将源代码(source code)编译成为托管模块(Managed Module)-->将托管模块组合成程序集-->加载CLR-->执行程序集代码


 一、将源代码编译为托管模块

   我们可以用任何支持CLR的编程语言来创建源代码文件,然后用相应的编译器来做语法检查和源代码分析,最终生成托管模块。托管模块是一个需要CLR才能执行的标准Windows可移植可执行(portable executable,简称PE)文件。

 《.NET框架程序设计》读书笔记一--.NET程序的生成以及执行过程_第1张图片

 二、将托管模块组合成程序集

   CLR并不直接和模块打交道,它直接打交道的是程序集(assembly)。
   对于程序集,简言之,有如下特点:
   A.程序集是一个或多个托管模块,以及一些资源文件的逻辑组合。
   B.程序集是组件复用,以及实施安全策略和版本策略的最小单位。

 《.NET框架程序设计》读书笔记一--.NET程序的生成以及执行过程_第2张图片

    
 三、加载CLR

   主要分为托管EXE加载CLR和托管DLL加载CLR。
 在Windows XP和Windows .NET服务器家族出现之前:
  EXE文件加载CLR的过程:
  托管EXE文件被调用时,Windows先加载该文件,发现其.idata部分记录了要把MSCorEE.dll(微软组件对象运行时执行引擎)加载到进程的地址空间(编译器在生成托管EXE文件时,x86 stub函数JMP _CorExeMain被嵌入到了PE文件的.text部分,而这个函数是从MSCorEE.dll中导入的,所以.idata部分会记录MSCorEE.dll).加载了MSCorEE.dll后,加载器获得_CorExeMain函数的地址,同时修正托管EXE中的stub函数的JMP指令。进程的主线程开始执行修正后的x86 stub函数,该函数会跳转到_CorExeMain函数上,_CorExeMain函数开始初始化CLR,并查看可执行程序集的CLR表头以确定要执行的托管入口点方法。随后IL代码被翻译成本地CPU指令。CLR跳转到编译后的本地CPU指令上,至此,托管应用程序开始真正运行。
   
  托管DLL加载CLR的过程类似,分为非托管代码加载托管DLL和托管代码加载托管DLL
  
  非托管代码加载托管DLL:

   1、Windows加载托管DLL,并自动加载MSCorEE.dll,获取MSCorEE.dll中_CorDllMain函数的地址,并修正托管DLL中x86 stub函数的JMP指令。
   2、调用LoadLibrary加载托管DLL的线程将跳到x86 stub函数上来,该函数会跳转到MSCorEE.dll中的_CorDllMain函数上。_CorDllMain函数开始初始化CLR,然后立即返回,应用程序也返回到正常状态继续执行。
    
     注:托管DLL中方法的IL代码只会在非托管代码明确调用时开始以即时编译的方法执行。


   托管代码加载托管DLL:

     调用代码会检查托管DLL中的元数据,然后以即时编译的方式执行其内方法的IL代码。

 《.NET框架程序设计》读书笔记一--.NET程序的生成以及执行过程_第3张图片

   Windows XP和Windows .NET服务器家族上,托管程序被调用时:

1、操作系统的加载器会查看PE表头的第14条目录项来检测该文件中是否包含托管代码。
2、如果目录存在且不为0,加载器将忽略该文件的导入部分.idata,而自动将
 MSCorEE.dll加载到进程地址空间内
3、加载完成后,操作系统的加载线程将直接跳转到MSCorEE.dll中相应的函数上。

文章来源: http://www.cnblogs.com/xlwei/archive/2008/04/17/1158746.html

你可能感兴趣的:(《.NET框架程序设计》读书笔记一--.NET程序的生成以及执行过程)