揭开CLR神秘面纱—第一步PE文件
熟悉.NET架构的都对CLR,CTS,IL等概念会很熟悉,但是对这些概念真正了解的很深入的人估计没有很多。在学习之余,想把自己对CLR的学习心得拿来跟大家沟通一下。
CLR(Common Language Runtime)提供了.NET应用程序都要使用的编程模型,包括文件加载器,内存管理器,安全系统,线程池等。并且能支持多种语言运行的一个平台。
我们都知道,每一种语言都有其自身的编译器,如C#有C#编译器。C有C编译器,那这些不同编译器编译出来的汇编指令或机器指令如何能统一在这么一个CLR环境中运行呢?
大家都会回答,这是IL的功劳。所有语言经过编译后都会转化成IL。没错,但是这并不全面。这些不同的语言之所以能在CLR中运行。单靠IL肯定是不行的。
事实上在.NET中,不管使用哪一种编译器,在CLR中其结果都是一个manage module(托管模块),这个模块就是我们标题里说的PE文件。PE(Portable Excutable)可移植执行体。
那么PE里面又包含哪些东西呢?
一个托管PE文件通常由4个部分构成:PE头,CLR头,元数据以及IL(中间语言)
那我们如何获取这些信息呢?我们开始一段最简单的代码。
2
3 {
4
5 static void Main(string[] args)
6
7 {
8
9 Console.WriteLine("Hello world");
10
11 }
12
13 }
14
然后我们利用ildasm打开他的中间语言。选择视图—》统计。会看到如下代码。
其中PE headersize就是PE头信息,CLR header size就是CLR头信息,meta-data size为元数据信息。Manage code就是IL信息。这几个部分分别起什么作用呢?
PE头:标准的windows PE文件头,分为PE32和PE32+两种格式,如果这个头使用PE32格式,则咱们的托管模块可在windows32位和64位版本上运行,如果标识为PE32+格式,则托管模块就只能在windows64位系统上运行。它还包含了文件类型,如是DLL还是GUI。如果可能,还会包含与本地CPU代码有关的信息。
CLR头:包含所要求的CLR版本,一些标志,托管模块入口方法(Main方法)的元数据标记。以及模块的元数据,资源等等信息。
元数据:其实对元数据这个词本身不好理解,我所理解的元数据就是表。这些表里模块本身的定义的一些类型和成员,就是定义表。还有包含引用的一些对象称之为引用表和清单表。关于这些可能会在以后专门介绍一下。
至于IL可能就不要多说了。就是咱们前面说的不同的编译器编译后生成的代码,程序运行的时候,CLR会将IL编译成本地CPU指令。
综合所述:代码被编译后,生成的PE文件中会包含以上所说的四个部分,这四个部分中PE头,CLR头和元数据记录了我们的程序运行的环境、程序运行时所需要的对象资源,这些资源通常分配在我们计算上的内存上。最后CPU指令把这一系列复杂的东西运行起来。就是我们的程序运行起来了。当然,这只是一个笼统的说法,其中很多的细节是如何处理的呢?线程如何执行?垃圾又是如何实现自动回收的呢?在以后的章节中,我们会继续学习这些。
版权声明:原创技术文章,如需转载,请务必声明出处。否则将追究法律责任