现在的位置: 首页 > 综合 > 正文

学习.NET (3) Inside GAC --浅析GAC目录架构在不同CPU平台上的工作原理

2013年09月01日 ⁄ 综合 ⁄ 共 2953字 ⁄ 字号 评论关闭

Inside GAC

--浅析GAC目录架构在不同CPU平台上的工作原理

By Alva Chien

File Version: 1.0

Released: 2007.5.30

 

GAC是用来存放可以被大部分Assembly引用的Assembly的地方,它的地址是:%SystemRoot@/AssemblyGAC中只能存放Strongly named assembly.NET Framework SDK提供了一个GACUtil.exe的工具来操作GAC

 

GAC 的大致结构

一个比较完整的.NET Framework 2.0GAC下子目录的结构如下所示:

GAC

GAC_32

GAC_MSIL

GAC_64

NativeImages1_v1.1.4322

NativeImages_v2.0.50727_32

NativeImages_v2.0.50727_64

其中:

GAC是用于存放基于.NET Framework 1.0/1.1创建的Assemblies,这些Assemblies只能运行在32-bit 地址空间。

GAC_MSIL用于存放基于.NET Framework 2.0上的无特定CPU指定的Assemblies,这些assemblies可以运行在32-bit地址空间或者64-bit地址空间。

GAC_32也是用于存放基于.NET Framework 2.0创建的基于x86架构的Assemblies,因为这些Assemblies可以拥有32-bitnative CPU代码,所以只能运行在32-bit空间,可以直接在32-bit系统上运行或者使用WOW64技术在64-bitOS系统上运行。

GAC_64用于存放.NET Framework 2.0上创建的基于x64或者IA64Assemblies,这些Assemblies可能含有x64或者IA64Native Code,所以他们只能运行在64-bit地址空间上。这个目录在32-bitOS上不存在。值得注意的是,GAC_64中的Assemblies是根据系统架构决定,在x64系统上,该目录中的Assemblies就必须是基于x64的,IA64Assemblies无法被装入,反之亦然。

NativeImages开头的目录存放的通过NGen.exe编译assembly生成的基于当前平台的非managed代码,这个目录不需要Strongly named Assemblies,后面的数字对应了版本号。而基于.NET Framework 2.0的两个NativeImages目录名称最后的两个字符’64’’ 32’则代表了对应的平台。

 

.NET Framework SDK安装的两份系统Assemblies

众所周知,.NET Framework SDK在安装时,会安装两份系统自带的Assemblies,一份存在GAC中,另外一份则存放于编译器和CLR所在的目录(%SystemRoot%/Microsoft.NET/Framework/versio_nnumber)。安装在CLR目录的那一份是跟当前系统相关的,也就是说,x64位的系统上,CLR目录中的Assemblies都是基于平台无关或者基于x64的。

编译一个引用了其他AssemblyAssembly时,编译器查找引用assembly的顺序是:

1) 当前工作目录

2) 编译器 (CSC.exe) 所在的目录

3) 编译器的/lib编译开关指定的目录

4) 当前系统环境变量LIB指定的目录

之所以会存在两份系统Assembly以及这样的查找顺序的根本原因就在于GAC内部的复杂结构,这样引用系统Assemblies,编译器可以直接从CLR所在目录读取对应的Assembly

 

一台机器容许存在同一个系统Assembly的多个版本 ,但是仅限于可以运行的多个版本,例如,x64平台上完全存在同一个系统Assemblyx86x64两个版本(其他的属性:比如名称,版本,Culture, Public key token都完全一致,GAC将这两个Assembly分别放在GAC_32GAC_64),但是x64平台不会存在IA64的版本,同样x86平台无法存在x64或者IA64版本。

 

因为CLR所在的目录只包含跟机器平台相吻合的系统Assembly版本,所以编译器而不管需要编译什么平台的Assembly时都将读取CLR中的版本 (x64版本),这样做的原因在于编译器只需要AssemblyMetadata部分 (包括Visual StudioIntelligent也只需要Metadata) ,而同一个Assembly的不同平台版本之间只有IL不同且Metadata完全相同,所以完全不影响编译,真正运行或调试时CLR会从GAC中装载正确的平台版本。

 

GAC详细结构

.NET Framework安装时会同时安装一个Windows Explorer扩展, SHFusion.dll,用于在Explorer中打开%SystemRoot%Assembly文件夹时显示一个可理解并User-kind的界面。

 

最简单而有效查看GAC内部文件结构的方法是使用cmd.exe。以GAC_MSIL为例子,其下面包含了大量的子目录:

.

..

Accessibility

AspNetMMCExt

CppCodeProvider

Cscompmgd

IEExecRemote

IEHost

IIEHost

Microsoft.AnalysisServices

Microsoft.AnalysisServices.AdomdClient

Microsoft.AnalysisServices.DeploymentEngine

……

其实这里子目录就是Assembly的名字,以System.Xml为例,其下只有一个子目录:

2.0.0.0_b77a5c561934e009

这个子目录的命名方式就是“版本号_PublicKeyToken”。这样即使两个Assembly不幸同名的话,也因为其版本号和PublicKeyToken(肯定不同)的不同而存放在不同的文件夹下。

 

总结

下表是.NET Framework 2.0安装的示意:

CPU

OS

详细

x86

32-bit OS

主要的Assembly安装在GAC_MSIL中,另外一部分会安装在GAC_32中。在CLR目录上安装一份CPU无关和x86平台的Assemblies

x64

32-bit OS (事实上这里的x64就是x86)

主要的Assembly安装在GAC_MSIL中,另外一部分会安装在GAC_32中。在CLR目录上安装一份CPU无关和x64平台的Assemblies

64-bit OS

主要的Assembly安装在GAC_MSIL中,另外一部分会安装在GAC_64中,GAC_64中只能存放x64结构的AssembliesGAC_32可能会被安装。在CLR目录上安装一份CPU无关和x64平台的Assemblies

IA64

64-bit OS

主要的Assembly安装在GAC_MSIL中,另外一部分会安装在GAC_64中,GAC_64中只能存放IA64结构的AssembliesGAC_32可能会被安装。在CLR目录上安装一份CPU无关和IA64平台的Assemblies

 

抱歉!评论已关闭.