很多人都说.net编译出来的exe文件不是真正的exe文件。
俺一开始也是这么认为的,但在经过一些了解后,发现这种说法其实完全不能真正说明.net 的exe文件的本质。
那.net 的exe文件到底是什么呢?
其实首先它还是一个exe文件。
但是这个exe文件需要一系列的dll的支持才能运行起来。
哪些dll呢,mscor***.dll说了,舍我其谁啊。
为什么这么说呢,至少有一个原因很能说明这个问题。
因为每个.net的exe文件都必然的在引用了一个dll,
mscoree.dll,没错啦,就是这个dll文件。而且还调用了一个名为CorExeMain的方法。
而这个方法就是大家耳熟能详的托管代码的进入点。调用这个方法前exe还在非托管的天空下飞翔,调用后就马上被***.dll打落下来,只能在托管代码的压制下匍匐前进了。
不知道这个比喻恰不恰当……
而.net exe和正常的win32 exe的最大区别还在于 图中的.NET irectory的节点上。
win32 exe是没有这个节点的。
在.NET irectory节点下,有两个子节点,分别是 MetaData Header(元数据头) MetaData Streams(元数据流)
如果把.NET irectory当成一本书的话,那么MetaData Header(元数据头)就相当于书的目录,而MetaData Streams(元数据流)就相当于书的内容了。
这里先重点说说书的内容,图上的MetaData Streams(元数据流)包含了5个节点,这些节点都被称为堆(heap),#~堆,#Strings堆等等。
但其实一个.net exe最多可以有6个堆,这里还少了一个#-堆(这个很不常见)。
现在说说堆的作用
#strings堆主要是用来保存程序里各种类名,方法名,成员名之类的数据,
#US堆则主要保存程序里的各种用户自己定义的字符串,比如 string s = "123",那么这个"123"就保存在这里了。而s则保存在#strings堆里去了。
#GUID和#Blob思义,一个保存GUID,一个保存二进制数据包括一些常量和强名称,方法签名之类的东西。
#~堆算是最重要的啦,这里保存了元数据表这个最重要的东西。
这个表里有什么东西呢?
这里保存了IL代码,那么就只有IL吗?
答案是——当然不是。
那么下篇再说吧,天晚了,睡觉了。
--------------------------------------------
元数据表共有4,50种之多,其中Method表里保存了IL。
还有其他很多表各自也保存了很多东西。
比如还有Module表,保存了关于模块的一些信息。
Assembly表保存了关于程序集的一些信息。
Type表保存了类,结构和枚举的信息。
其中Field,Method,Property,MemberRef还有签名的数据。这些表的结构里都有一个Signature字段,代表签名的偏移,签名一般都是二进制数据,所以偏移的是#Blob堆。