CLR和Windows加载器

在Windows上运行的应用程序可以通过多种不同的方式来启动。Windows负责处理所有的相关工作,包括设置进程地址空间、加载可执行程序, 以及指示处理器开始执行等。当处理器开始执行程序指令时,它将一直执行下去,直到进程退出。在本章的前面已经讨论过,在.NET应用程序中并不包含机器指 令。因此,在处理器开始执行前,首先需要将中间语言转换为机器指令。尽管存在着这种差异,.NET应用程序仍然可以采取与非托管应用程序一样的启动方式。 为什么这种方式可行?Windows加载器是否知道.NET应用程序的一些特定信息,因此能够自动地启动CLR?答案在于Windows上一种由来已久的 文件格式:可移植的可执行文件格式(Portable Executable,PE)。在图2-3中给出了PE映像文件的一般结构。

为了支持PE映像的执行,在PE的头部包含了一个域叫做AddressOfEntryPoint。这个域表示PE文件的入口点(Entry point)位置。在.NET程序集中,这个值指向.text段中的一小段存根(stub)代码。下一个重要的域就是数据目录(data directory)。当.NET编译器生成程序集时,它会在PE文件中增加一个数据目录项。具体来说,这个数据目录项的索引为15,其中包含了CLR头 的位置和大小。然后,根据这个位置在PE文件中找到位于.text段中的CLR头。在CLR头中包含了一个结构IMAGE_COR20_HEADER。在 这个结构中包含了许多信息,例如托管代码应用程序的入口点,目标CLR的主版本号和从版本号,以及程序集的强名称签名(strong name signature)等。根据这个数据结构中包含的信息,Windows可以知道要加载哪个版本的CLR以及关于程序集本身的一些最基本信息。 在.text段中还包含了程序集的元数据表,MSIL以及非托管启动存根代码。非托管启动存根代码包含了由Windows加载器执行以启动PE文件执行的 代码。

在接下来的章节中,我们将看到Windows加载器如何加载非托管映像和.NET程序集。

原文地址:https://www.cnblogs.com/shihao/p/2500791.html