托管程序的执行模型大致如下:

  1. 编译源代码为程序集(dll或exe文件),程序集包括了记录相关信息的元数据IL代码
  2. 执行程序集文件时,启动CLR,JIT负责把IL编译为本地代码并执行

IL是微软推出的一种面向对象的类似汇编指令集合的中间语言,无论是C#还是VB代码,经过不同的编译器可编译为无差别的IL,或者说单看IL代码是无法分辨出它是来自C#还是VB,IL类似于Java的.Class文件,该文件具有平台无关性,这使得.Net程序具备了像Java那样跨平台的条件。

程序集的组成及编译

程序集就是平时我们看到的由源代码编译产生的dll或exe文件,程序集是一个windows PE文件,和Java界的jar文件差不多在一个逻辑层次上。

下面来分别介绍程序集的组成结构以及如何从源代码编译为一个程序集:

程序集的组成部分

一个程序集文件的组成如下:

PE头

包括如下信息:文件运行在32位系统还是64为系统上;文件类型是GUI,CUI还是DLL,文件的生成时间等

CLR头

包含以下信息:CLR版本;入口方法;元数据,资源的位置等

清单

包含了程序集本身的一些信息,如:名称,版本,模块,资源等

元数据

包含以下信息:源代码定义的类型和成员;源代码应用的类型和成员,Vistual studio的智能感知就是靠读取元数据实现的

IL代码

如题

资源

嵌入程序集的图片,声音等资源

模块

上述的内容都包含在模块中,一个程序集文件可以包含一到多个模块,可以手动使用csc命令编译多模块程序集,使用Visual studio 编译的程序集默认都是单模块的,关于更详细模块的介绍可以看这本书:《.NET之美:.NET关键技术深入解析

欲了解程序集文件更详细的内容,请参考博客园牛人Anders Liu多年前制作的工具,这个工具可以打开一个程序集文件,查看里面的结构。目前Anders Liu又在GitHub上面创建了新项目peviewer,基于.Net core。

编译源代码为程序集

编程简单程序如下:

public class Program
{
public static void Main()
{
System.Console.WriteLine("Hello");
}
}

保存为d:\test\program.cs,打开“VS2015 开发人员命令提示”,执行如下命令:

csc.exe /out:d:\test\program.exe \t:exe \r:MsCorLib.dll d:\test\program.cs

执行该命令即可生产程序集program.exe文件。上述命令中,/out:后面为要生成的程序集文件名称,\r:后面为要引用的程序集文件名,上述程序中的System.Console类即包含于此dll文件中,由于MsCorLib.dll是.Net Framwork最为核心的程序集,编译器默认加载,所以上面的程序也可省略\r:选项。\t:选项表示生成的程序集的类型,可以接“exe”或“winexe”,前者表示生成的是一个控制台程序集,后者表示生成的是图形界面程序集,由于编译器默认的选项就是“exe”,所以上述命令中/t:选项也可省略。省略后的命令如下:

csc.exe /out:d:\test\program.exe d:\test\program.cs

另外一个重要的概念是“respones file”,在csc.exe文件所在目录,即C:\Windows\Microsoft.NET\Framework\vX.X.X下面,有一个名称为csc.rsp的文件,该文件被称为“respones file”,其默认内容如下:



正如你想象的,执行csc.exe时,该命令会自动读取这个文件中记录的选项,可以修改此文件加入自己想要的选项,也可以自己新建一个respones file 如“myrsp.rsp",然后像这样执行命令:

csc.exe @d:\test\myrsp.rsp /out:d:\test\program.exe d:\test\program.cs

更多的命令选项请看这里:https://msdn.microsoft.com/en-us/library/2fdbz5xd.aspx

运行程序集

托管代码的运行需要寄宿于操作系统提供的非托管的进程中,执行exe文件启动一个进程,该进读取CLR头后加载CLR,CLR启动后接管后续操作,包括内存管理,垃圾回收,异常管理等,在一个操作系统进程内部CLR又维护了一个或多个相当于轻量级进程被称为App Domain的逻辑隔离,不过,通常的程序大部分都是一个App Domain,关于App Domain的介绍可以参考:

CLR使用JIT编译器编译IL为本地CPU指令,JIT编译器可根据CPU的不同而生成不同的CUP指令,仅当方法被一次执行时才会被编译为CUP指令,再次执行则读取编译好的指令。这也是为什么.Net程序在刚启动时较慢的原因,一个解决办法是使用NGen.exe工具直接将IL编译为本地CPU指令,但是存在一个同步的问题,及如果执行环境(换了CPU,CLR版本变化等)改变了,原来编译好的指令可能无法运行。另外使用NGen.exe编译来的CPU指令不会像JIT那样了解CPU的特点而能生成较为优化的指令,所有执行效率要低一些。

参考资料

  • 《CLR via C#》
  • 《.NET之美:.NET关键技术深入解析》

CLR via C# 摘要一:托管程序的执行模型的更多相关文章

  1. C++手动加载CLR运行托管程序(CLR Hosting)

    转载自:http://www.linuxidc.com/Linux/2012-10/72293.htm 机制介绍 有些时候主程序是通过C/C++实现的,但是我们希望通过托管代码来扩展非托管程序,从而也 ...

  2. CLR via C# 摘要二:IL速记

    最简单的IL程序 .assembly test {} .method void Func() { .entrypoint ldstr "hello world" call void ...

  3. 通过修改CoreCLR中的ClrHost实现自托管程序

    上一篇我们讲了如何在windows和Linux上编译CoreClr的问题 虽然文章使用的是windows 10 (Bash)环境,但是也可以做为ubuntu环境的参考. 成功编译CoreCLR的源代码 ...

  4. 重温CLR(十五) 托管堆和垃圾回收

    本章要讨论托管应用程序如何构造新对象,托管堆如何控制这些对象的生存期,以及如何回收这些对象的内存.简单地说,本章要解释clr中的垃圾回收期是如何工作的,还要解释相关的性能问题.另外,本章讨论了如何设计 ...

  5. 托管程序调用非托管dll问题总结

    托管程序Visual Basic.net, 非托管DLL标准C++程序(使用VC++编译) 函数调用定义 第一种写法: <DllImportAttribute("XXX.dll&quo ...

  6. CLR 的执行模型(2)

    第一章 CLR 的执行模型(2) 本篇内容大纲 Framework 类库(Framework Class Library , FCL) 通用类型系统(Common Type System,CTS) 公 ...

  7. CLR执行模型

    好好学习底层运行机制,从CLR via C# 开始. CLR的执行模型: CLR:Common Language Runtime,是一个可由多种编程语言使用的"运行时".CLR的核 ...

  8. 【C#进阶系列】01 CLR的执行模型——一个Hello World的故事

    好吧,废话少说,先上一章Hello World图: 我们有了一个Hello world程序,如此之简单,再加上我今天没有用汉字编程o(>﹏<)o,所以一切很简单明了. 故事开始: 编译: ...

  9. 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型

    .Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...

随机推荐

  1. 从零开始编写自己的C#框架(27)——什么是开发框架

    前言 做为一个程序员,在开发的过程中会发现,有框架同无框架,做起事来是完全不同的概念,关系到开发的效率.程序的健壮.性能.团队协作.后续功能维护.扩展......等方方面面的事情.很多朋友在学习搭建自 ...

  2. Redis百亿级Key存储方案(转)

    1 需求背景 该应用场景为DMP缓存存储需求,DMP需要管理非常多的第三方id数据,其中包括各媒体cookie与自身cookie(以下统称supperid)的mapping关系,还包括了supperi ...

  3. C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程

    前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...

  4. Html.DropDownLis绑定数据库

    效果: 方法一: View: <div class="col-md-md-4"> <div class="input-group"> & ...

  5. iOS从零开始学习直播之2.采集

      直播的采集由采集的设备(摄像头.话筒)不同分为视频采集和音频采集,本篇文章会分别介绍. 1.采集步骤   1.创建捕捉会话(AVCaptureSession),iOS调用相机和话筒之前都需要创建捕 ...

  6. Winserver2012下mysql 5.7解压版(zip)配置安装

    一.安装 下载mysqlzip版本mysql不需要运行可执行文件,解压即可,下载zip版本mysqlmsi版本mysql双击文件即可安装,相对简单,本文不介绍此版本安装 配置环境变量打开环境变量配置页 ...

  7. OpenGL shader 中关于顶点坐标值的思考

    今天工作中需要做一个事情: 在shader内部做一些空间距离上的计算,而且需要对所有的点进行计算,符合条件的显示,不符合条件的点不显示. 思路很简单,在vertex shader内知道顶点坐标,进行计 ...

  8. 了解 ARDUINO 101* 平台

    原文链接 简介 作为一名物联网 (IoT) 开发人员,您需要根据项目的不同需求,选择最适合的平台来构建应用. 了解不同平台的功能至关重要. 本文第一部分比较了 Arduino 101 平台和 Ardu ...

  9. 整体二分QAQ

    POJ 2104 K-th Number 时空隧道 题意: 给出一个序列,每次查询区间第k小 分析: 整体二分入门题? 代码: #include<algorithm> #include&l ...

  10. ASP.NET Core 性能对比评测(ASP.NET,Python,Java,NodeJS)

    前言 性能是我们日常生活中经常接触到的一个词语,更好的性能意味着能给我们带来更好的用户体检.比如我们在购买手机.显卡.CPU等的时候,可能会更加的关注于这样指标,所以本篇就来做一个性能评测. 性能也一 ...