深入了解CLR的加载过程 📅 2026/7/6 2:50:50 我们知道.net编译器在生成托管代码时会将一些重要信息写入PE文件的header和.text section(后边我会介绍这些写入程序集的重要信息是什么)本文介绍当我们双击一个托管代码写的exe程序时发生的事情。以下说明所使用的工具是VS2005sos.dll示例程序代码如下usingSystem;usingSystem.Collections.Generic;usingSystem.Text;namespacehello{classProgram{staticvoidMain(string[] args){Int32 a1;Int32 b2;bab;Console.WriteLine(b);Console.ReadKey();}}}那么CLR是如何被加载的呢1、当你双击一个.exe文件时Windows操作系统提供的PE Loader会将该exe文件载入内存(1)、首先明确一点PE Loader问什么能加载exe文件呢因为exe文件就是一种PE文件PE(Portable Execute)文件是微软Windows操作系统上的程序文件EXE、DLL、OCX、SYS文件以及COM组件都是PE文件。(2)、有必要了解一下PE文件的结构图 11) Dos stub由100个左右的字节所组成用来输出类似“这个程序不能在DOS下运行”这样的错误信息2) PE SignatureDWORD类型PE文件签名用来表示这是个PE文件用ASCII码表示3) File Header包含PE文件最基本信息通过dumpbin可以看到如图2所示从这里可以看到CPU类型为14c是Intel I386、I486或者I586section的数量为2链接器产生这个文件的日期COFF符号表的文件偏移量为0COFF符号表的符号数目为0Optional Header的大小。图24) Optional Header用来存储除了基本信息以外的其他重要信息具体含义大家可以查阅PE文件格式的相关资料我这里对一些关心的域根据图3进行一下说明-- entry point指明这个PE文件的入口地址是一个RVA(相对虚拟地址)-- base of code代码块起始地址的RVA在内存中代码块通常在PE首部之后数据块之前-- base of data数据块-- image basePE文件被链接器重定位后的内存地址可以是链接器优化节省载入时间和空间-- subsystem可执行文件的用户界面使用的子系统类型。具体值的含义为1不需要子系统比如设备驱动2在Windows图形用户界面子系统下运行3在Windows字符子系统下运行控制台程序5在OS/2字符子系统下运行仅对OS/2 1.x7在Posix字符子系统下运行所以可以看到我们的程序是一个控制台程序。--最后定义了一些数据目录具体内容不再赘述。图 35)section headerSection header可以有一个或多个见图4、图5、图6。-- name表示这个section的名字例如这个section的名字为.text-- virtual address保存section中数据被载入内存后的RVA-- file pointer to raw data从文件开头到section中数据的偏移量。图 4-- Section的原始数据图 5