• CLR via C#


    博客园对markdown支持不佳,错乱移步Github IO 博文

    CLR 的执行模型

    模块/程序集

    1.模块

    托管模块组成部分

    • PE32/PE32+头 : PE即Portable Executable表示可执行文件
    • CLR头 : 包含所需的CLR版本,Main方法入口
    • 元数据 : 元数据是一组数据表.其中的一些数据表描述了模块中定义的内容,比如类型或成员。还有一些描述了托管模块引用的内容,比如导入的类型、成员。
    • IL代码

    元数据用途

    1. 用于编译,消除了C/CPP时期对头文件的依赖
    2. VS IntelliSense,VS读取程序集的元数据,提供代码提示
    3. 允许垃圾回收器追踪对象的生存期,CLR GC采用的是Mark-Sweep形式,在mark阶段,元数据可以提供某一对象的某一字段引用了哪个其他的对象,可以把引用的对象也mark一下,防止被GC回收

    2.程序集

    程序集是一个或多个模块/资源 文件的逻辑分组。程序集是重用、安全性、以及版本控制的最小单元。一般认为一个dll/exe是一个程序集,但是还可以生成多文件程序集,使用AL.exe

    如何判断是否安装了.NET Framework,只需检查%SystemRoot%System32MSCorEE.dll文件即可
    如图,文件说明写出是 .NET Runtime Execution Engine

    执行程序集中的代码 JIT

    当一个方法第一次执行时,CLR内部的某个表会为该方法所在类型的所有方法创建一个记录项,对应着一个地址,在JIT编译IL => Native code时查找IL代码,JIT编译好的Native Code存放在内存中,并更新表中的地址,也就是下一次调用该方法时,直接执行的是Native Code,不用再次经过JIT了。这个不用是在一个程序的执行时间内,要是将程序关闭了,再打开还得重来。.NET都是半解释性性语言。

    CTS : 通用类型系统
    CLS : 通用语言规范
    由于各个语言实现的不尽一致,MS定义了一个公共语言规范(Common Language Specification),它详细定义了一个最小功能集.
    例如使用[assembly:CLSCompliant(tue)]指定此程序集是CLS兼容的

    public UInt32 Abc()
    public int Xyz()
    public int xyz()
    

    以上会得到警告,因为有的语言没有unsigned int,而Xyz和xyz方法,是依靠大小写来区分的,像VB 就不能区分这两个方法.

    在CLS中,类型的成员要么是一个字段,要么是一个方法,像是C#提供的属性(Property),事件(event)/委托(delegate)/运算符重载 都是C#编译器提供的,到IL层,只有字段和方法.delegate会变成一个类,这个另说.

    程序集生成/打包/部署

    csc.exe csharp compiler

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

    csc /out:hello.exe /target:exe hello.cs

    • /out表示 输出文件
    • /target 或者 /t 表示输出类型
      1. exe 表示CUI,控制台窗口
      2. winexe GUI应用程序
      3. library 生成dll
      4. module 生成.netmodule模块,/addmodule:添加module引用
    • /reference: 或 /r 表示添加引用

    csc hello.cs会生成hello.exe
    /out:hello.exe 和 /t:exe 是默认的

    CSC编译时默认引用MSCorLib.dll,可以指定/nostdlib使程序不默认引用这个

    响应文件(.rsp)

    在CSC编译的时候,/r /t /out 命令可以保存在一个文件了,如MyProj.rsp

    csc @MyProj.rsp hello.cs
    

    还会在CSC.exe 相同目录中查找一个全局的CSC.rsp文件,例如我的电脑上是C:WindowsMicrosoft.NETFrameworkv4.0.30319csc.rsp里面Reference了一堆基本的dll,使用/noconfig指定编译时忽略这个全局响应文件

    使用/r:xxx.dll来引用一个dll时,查找路径为

    1. 工作目录,当前目录
    2. CSC.exe所在目录,MSCorLib.dll从这个文件获取
    3. /lib编译时指定 or LIB环境变量

    将模块合并成程序集

    hello.cs

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

    method.cs

    public class Method
    {
    	public static void AStaticMethod()
    	{
    		System.Console.WriteLine("Hello from another module ...");
    	}
    }
    

    执行

    csc /t:module method.cs
    csc /addmodule:method.netmodule hello.cs
    hello
    

    结果

    生成的netmodule文件是一个不包含清单元数据表的PE文件,添加到一个程序集后,这个netmodule不能删除,删除会抛出FileNotFoundException

    未经处理的异常:  System.IO.FileNotFoundException: 未能加载文件或程序集“method.n
    etmodule”或它的某一个依赖项。系统找不到指定的文件。 ---> System.IO.FileNotFound
    Exception: 系统找不到指定的文件。 (异常来自 HRESULT:0x80070002)
       --- 内部异常堆栈跟踪的结尾 ---
       在 Hello.Main()
    

    使用AL.exe 程序连接器

    al.exe /t:library /out:example.dll a.netmodule b.netmodule
    

    使用
    /link[resource]连接资源
    /resource 嵌入资源

    程序集的私有部署

    探测目录

    1. AppDirABC.dll
    2. AppDirABCABC.dll
    3. AppDirprivatePathABC.dll
    4. AppDirprivatepathABCABC.dll

    privatePath在app.config中配置

    <configuration>
        <runtime>
            <assemblyBinding>
                <probing privatePath="Private"
    ...
    

    强命名程序集

    sn -k magicdawn.snk //创建一个snk,包含私钥公钥
    csc /keyfile:magicdawn.snk hello.cs
    

    或者

    sn -p magicdawn.snk magicdawn.PublicKey //创建两个,publickey只包含公钥
    sn -tp magicdawn.PublicKey //查看公钥
    
  • 相关阅读:
    win2003服务器网站和数据库的二周自动备份
    尝试jquery插件的开发
    Git 代码版本管理
    实验三、UML 建模工具的安装与使用
    实验五 单元检测
     实验四 代码评审
    实验二 结队编程(第二阶段)
    结队编程
    第一次实验
    用live writer发布文章文章中含时产生的bug
  • 原文地址:https://www.cnblogs.com/magicdawn/p/clr-basics.html
Copyright © 2020-2023  润新知