启动.net应用程序时会发生什么?

我一直在使用.net开发应用程序已有一段时间了。 但是,我仍然不确定CLR是如何知道.net应用程序已经启动的。 是否每个应用程序都有一个CLR实例? 我不认为这可能是这种情况,因为只有一个GC管理所有.net应用程序的所有内存。 CLR是否在后台运行? 我很困惑。

嗯,让我来看看这个。

  1. 有人用C#或.NET’中间语言’或其他托管语言构建.NET应用程序。

  2. 该语言的编译器csc.exe(C#)或ilasm.exe(字节码汇编程序)或其中的任何一个生成PE可执行文件。 PE可执行文件具有编译器或汇编程序填充的特定结构。 那包括:

    • 一个切入点,和
    • 它使用的动态库列表(IMPORT表)。 其中一个库是mscoree.dll
    • 大量元数据,包括目标.NET运行时版本
  3. 单击可执行文件,从命令行运行或从Win32 API执行时, Windows加载程序实现 (在NTDLL.dll中)接管

  4. 加载程序代码负责将可执行文件存入内存,根据需要加载动态链接库,将链接库映射到可执行代码可以访问它们的位置,以及使用映射库的实际地址更新导入地址表。

  5. 一旦准备就绪,加载器就跳转到入口点(通过我假设的是一些恶作剧从内核空间切换到用户空间,或者转换到保护模式,因为应用程序在它自己的受保护的32位或64位内存空间中运行)。 入口点是mscoree.dll – .NET公共对象运行时执行引擎,它刚刚映射到进程内存中。 我已经看到这个DLL被称为.NET启动垫片,它允许在一台机器上存在多个.NET安装。 如果您在自己的常规应用程序中嵌入.NET语言,则Mscoree.dll是您将使用的库。

  6. Mscoree.dll查看从PE可执行文件加载的元数据,特别是CLR标头和目标.NET运行时版本。 从它可以CorBindToRuntimeEx 2到正确的CLR版本。

  7. CorBindToRuntimeEx加载正确的.NET运行时实现(并返回一个指向COM接口的指针,允许您调用该.NET运行时。此代码从%WINDIR%\ Microsoft.NET \ Framework \ v ####中的dll加载#。

  8. 我不确定是谁,但可能是mscoree shim使用.NET ICLRRuntimeHost接口指针来调用方法来初始化.NET运行时,垃圾收集器,IL解释器,JIT和IHostControl接口(允许.NET解释器到回到托管过程),最终告诉Interpreter开始执行编译应用程序的IL代码。

(我学到了很多东西 – 这些链接背后有很多信息,我当然没有完全了解所有这些!)

http://msdn.microsoft.com/en-us/library/xh0859k0.aspx

http://my.safaribooksonline.com/book/programming/microsoft-dotnet/0735619883/a-tour-of-the-clr-hosting-api/ch02lev1sec3

http://msdn.microsoft.com/en-us/magazine/bb985994.aspx

Windows可执行文件是可移植可执行文件 ,这种格式为Windows提供加载和运行程序所需的信息。 当Windows遇到.NET程序时,它会加载CLR的一个实例,并将程序的执行交给新的CLR实例。 每个运行的.NET程序都托管在它自己的CLR实例中。

CLR进程加载IL程序并将其编译为本机代码(JIT),然后执行代码,负责该程序的内存管理和垃圾收集。