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

  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. CSS HTML元素布局及Display属性

    本篇文章主要介绍HTML的内联元素.块级元素的分类与布局,以及dispaly属性对布局的影响. 目录 1. HTML 元素分类:介绍内联元素.块级元素的分类. 2. HTML 元素布局:介绍内联元素. ...

  2. scrapy爬虫docker部署

    spider_docker 接我上篇博客,为爬虫引用创建container,包括的模块:scrapy, mongo, celery, rabbitmq,连接https://github.com/Liu ...

  3. 一起学微软Power BI系列-使用技巧(3)Power BI安卓手机版安装与体验

    Power BI有手机版,目前支持安卓,苹果和WP,不过没有WP手机,苹果在国内还不能用,要FQ和用就不测试了.安卓的我也也是费了九牛二虎之力才把app下载下来,把方法分享给大家. FQ太麻烦,所以建 ...

  4. 集合(set)-Python3

    set 的 remove() 和 discard()  方法介绍. 函数/方法名   等价操作符 说明 所有集合类型 len(s)   集合基数:集合s中元素个数 set([obj])   可变集合工 ...

  5. HTTP API接口安全设计

    HTTP API接口安全设计 API接口调用方式 HTTP + 请求签名机制   HTTP + 参数签名机制 HTTPS + 访问令牌机制 有没有更好的方案? OAuth授权机制 OAuth2.0服务 ...

  6. CSS3自定义滚动条样式 -webkit-scrollbar(转)

    有没有觉得浏览器自带的原始滚动条很不美观,同时也有看到很多网站的自定义滚动条显得高端,就连chrome32.0开发板都抛弃了原始的滚动条,美观多了.那webkit浏览器是如何自定义滚动条的呢? 前言 ...

  7. Android Studio —— 创建Menu菜单项

    大多数android程序的右上角都会设置一个菜单按钮比如微信的界面右上角的加号. 这个需要在layout同级目录下新建文件夹命名为menu,再右击新建的menu新建xml文件:

  8. AndroidStudio — Error:Failed to resolve: junit:junit:4.12错误解决

    原博客:http://blog.csdn.net/u013443865/article/details/50243193 最近使用AndroidStudio出现以下问题: 解决:打开app下的buil ...

  9. Maven常用命令

    开发中常用的命令: 1. mvn compile 编译源代码2. mvn test-compile 编译测试代码3. mvn test 运行测试4. mvn package 打包,根据pom.xml打 ...

  10. 深入学习HBase架构原理

    HBase定义 HBase 是一个高可靠.高性能.面向列.可伸缩的分布式存储系统,利用Hbase技术可在廉价PC Server上搭建 大规模结构化存储集群. HBase 是Google Bigtabl ...