CLR via C# 摘要一:托管程序的执行模型
托管程序的执行模型大致如下:
- 编译源代码为程序集(dll或exe文件),程序集包括了记录相关信息的元数据和IL代码
- 执行程序集文件时,启动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的介绍可以参考:
- http://www.cnblogs.com/awpatp/archive/2009/11/24/1609570.html
- https://msdn.microsoft.com/en-us/library/cxk374d9.aspx
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# 摘要一:托管程序的执行模型的更多相关文章
- C++手动加载CLR运行托管程序(CLR Hosting)
转载自:http://www.linuxidc.com/Linux/2012-10/72293.htm 机制介绍 有些时候主程序是通过C/C++实现的,但是我们希望通过托管代码来扩展非托管程序,从而也 ...
- CLR via C# 摘要二:IL速记
最简单的IL程序 .assembly test {} .method void Func() { .entrypoint ldstr "hello world" call void ...
- 通过修改CoreCLR中的ClrHost实现自托管程序
上一篇我们讲了如何在windows和Linux上编译CoreClr的问题 虽然文章使用的是windows 10 (Bash)环境,但是也可以做为ubuntu环境的参考. 成功编译CoreCLR的源代码 ...
- 重温CLR(十五) 托管堆和垃圾回收
本章要讨论托管应用程序如何构造新对象,托管堆如何控制这些对象的生存期,以及如何回收这些对象的内存.简单地说,本章要解释clr中的垃圾回收期是如何工作的,还要解释相关的性能问题.另外,本章讨论了如何设计 ...
- 托管程序调用非托管dll问题总结
托管程序Visual Basic.net, 非托管DLL标准C++程序(使用VC++编译) 函数调用定义 第一种写法: <DllImportAttribute("XXX.dll&quo ...
- CLR 的执行模型(2)
第一章 CLR 的执行模型(2) 本篇内容大纲 Framework 类库(Framework Class Library , FCL) 通用类型系统(Common Type System,CTS) 公 ...
- CLR执行模型
好好学习底层运行机制,从CLR via C# 开始. CLR的执行模型: CLR:Common Language Runtime,是一个可由多种编程语言使用的"运行时".CLR的核 ...
- 【C#进阶系列】01 CLR的执行模型——一个Hello World的故事
好吧,废话少说,先上一章Hello World图: 我们有了一个Hello world程序,如此之简单,再加上我今天没有用汉字编程o(>﹏<)o,所以一切很简单明了. 故事开始: 编译: ...
- 01.由浅入深学习.NET CLR 基础系列之CLR 的执行模型
.Net 从代码生成到执行,这中间的一些列过程是一个有别于其他的新技术新概念,那么这是一个什么样的过程呢,有什么样的机制呢,清楚了这些基本的东西我们做.Net的东西方可心中有数.那么,CLR的执行模型 ...
随机推荐
- WebApi接口 - 如何在应用中调用webapi接口
很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...
- 【绝对干货】仿微信QQ设置图形头像裁剪,让你的App从此炫起来~
最近在做毕业设计,想有一个功能和QQ一样可以裁剪头像并设置圆形头像,额,这是设计狮的一种潮流. 而纵观现在主流的APP,只要有用户系统这个功能,这个需求一般都是在(bu)劫(de)难(bu)逃(xue ...
- Python多线程爬虫爬取电影天堂资源
最近花些时间学习了一下Python,并写了一个多线程的爬虫程序来获取电影天堂上资源的迅雷下载地址,代码已经上传到GitHub上了,需要的同学可以自行下载.刚开始学习python希望可以获得宝贵的意见. ...
- servlet 简介,待完善
什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③ 这个在服务器端运行,用以处理客户端的请求 Servlet相关包的介绍--javax. ...
- Java程序员应该了解的10个面向对象设计原则
面向对象设计原则: 是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorat ...
- animate.css(第三方动画使用方法)
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 17.0px Monaco; color: #a5b2b9 } animation 语法: animatio ...
- https 安全验证问题
最近为了满足苹果的 https 要求, 经过努力终于写出了方法 验证 SSL 证书是否满足 ATS 要求 nscurl --ats-diagnostics --verbose https://你的域名 ...
- 编写简单的Makefile文件
makefile中的编写内容如下: www:hello.c x.h gcc hello.c -o hello clean: rm hello www:hello.c x.h 表示生成www这个文件需 ...
- Spring Security OAuth2 开发指南
官方原文:http://projects.spring.io/spring-security-oauth/docs/oauth2.html 翻译及修改补充:Alex Liao. 转载请注明来源:htt ...
- Linux CentOS7通过yum命令安装Mono(尝先安装模式)
前言 经过尝试网上各种安装mono的技术贴,这个安装过程经历了大约2周,尝试了各个版本,几目前博客所描述的所有安装方式.以下内容的安装方式可以为你尝试不同版本的mono.并非正式环境安装标准方式安装. ...