- .NET Core 2.0 应用程序高级调试:完全掌握Linux、macOS和Windows跨平台调试技术
- 李争
- 3674字
- 2021-04-02 03:44:50
1.1 .NET Core到底是什么
最近.NET领域的名词是越来越多了。.NET Framework、.NET Standard以及.NET Core等不一而足。因此非常有必要了解清楚.NET技术领域中的一些重要的名词和概念。
概括地说,.NET Core是一种小型的、高效的,可以通过文件复制直接部署的跨平台框架。由于.NET Core的开放性,使用.NET Core构建的应用程序既可以是框架相关的,也可以是框架独立的。
其实广大开发者非常关注.NET Core的真正原因,主要有两个:一是.NET Core自身开源,并鼓励更多的.NET项目开源;另一个是.NET Core支持跨平台特性,可以在Windows、Linux的多个发行版本、macOS和UNIX上运行。下面介绍.NET Core的主要特性。
1.1.1 从软件许可协议说开源
由微软牵头组建的.NET基金会(.NET Foundation http://dotnetfoundation.org/)的重要资产就是.NET Core的源代码以及.NET Core周边的一些开源项目。与其他开源基金会显著不同的是,.NET Foundation基金会的开源项目基本上都遵循MIT许可协议。这使得.NET Core的源代码具有极大的开放性和移植性。
当前开源软件世界有四个较为主流的软件许可协议。是的,开源软件也要尊重作者的知识产权。并不是开源了,代码就可以随意使用。这四个主流的许可协议分别是GPL、Apache、BSD和MIT。
由于这四个许可协议的文本主要是由英语写成,中国的开发者对这些协议文本并不是非常了解。概括地说,GPL的许可协议对开源软件的使用限制最为严格,并且具有极高的传染性。它的核心思想是让世界上的软件都开源分享。看起来很不错吧?但是它的传染性体现在:任何软件只要使用了GPL许可协议下的开源软件代码,这里的使用是指,引用GPL项目的库函数、修改源代码或者使用衍生后的源代码,那这个软件也就必须遵循GPL协议。也就是说,这个软件也必须免费和开源。这对商业软件就构成了极大的挑战。在中国走出去的战略下,如果一个商业软件公司使用了GPL开源软件作为其商业软件的一部分,那么在海外就有因为软件侵权而被告上法庭的风险。
后来,人们觉得GPL许可协议太严格了,社会对开源的认识水平与期望还有很大的差距。于是推出了另一个变体,也就是LGPL许可协议。LGPL许可协议相较于GPL许可协议的重大变化是:商业软件如果仅仅是链接和引用LGPL许可协议下的软件,那么就无须开源。但是,如果对LGPL许可协议下的项目的源代码进行了修改再使用,那么软件还是要求必须开源和免费。
开源界另一个著名的许可协议是阿帕奇(Apache)协议,这是由阿帕奇基金会创立的软件许可协议,广泛地存在于Apache系列软件技术栈之中,大家熟知的Spark、Storm以及Kafka都是阿帕奇基金会旗下的开源软件项目。阿帕奇协议相比GPL软件许可协议来说就宽松了许多,主要是鼓励开源软件的使用者充分尊重软件的原作者。如果自己的软件中使用了阿帕奇软件许可协议下的软件,那么就必须在软件中充分注明阿帕奇软件许可协议以及该开源软件的作者信息。如果对阿帕奇系列软件进行了修改,那就必须在发布时进行专门的说明。对于使用阿帕奇开源项目的软件是否可以闭源的问题,阿帕奇软件许可是允许不开放源代码的。当然,这一切都是尊重原作者的前提之下,比如保留阿帕奇的版权声明。
其实最开放的软件许可协议是BSD和MIT协议。这两个协议鼓励开发者自由地使用、修改和发布开源软件的代码。只要在源代码文本中保留原作者的版权信息就好。截取代码的片段、完整地编译和使用BSD或者MIT协议下的开源软件都是允许的。BSD协议还规定,如果对BSD协议下的软件进行源码修改再发布,则不得借用该项目原作者的名义进行宣传,估计是怕没改好毁名声吧。
.NET Core全系列的开源项目都采用MIT开源软件许可协议,你猜得没错,这里的MIT就是那个麻省理工学院(Massachusetts Institute of Technology)的意思。因此.NET Core可以被开发者近乎无限制地修改、移植并打包再发布。这才是.NET Core可以跨平台的原动力。
1.1.2 构成.NET Core的重要组件
其实现在通常所说的.NET Core并不是一个开源项目,而是由多个开源项目构成的一个项目集。其核心是四个支柱项目:CoreCLR、CoreFx、CLI和Roslyn。
1.CoreCLR项目介绍
CoreCLR是最核心的部分,也就是.NET公共语言运行时,对应到Java世界就是JRE,就是Java虚拟机。CoreCLR主要是用C++写成,支持使用MSC++、gcc和Clang等编译器进行编译。
CoreCLR项目是由.NET Framework的CLR源代码迁移而来。结构与.NET Framework基本保持一致。其中含有几个重要的组件:Class Loader、GC、JIT和Exception Handler等。
Class Loader负责把磁盘上编译过的中间语言代码段加载到内存中。.NET Core中的所有引用类型都是通过Class Loader加载到内存中。
GC,即垃圾收集器(Garbage Collection),是.NET Core实现内存自动化管理的重要组件。GC会一直关注内存的变化,在适当的时候启动并对内存中无效的对象执行销毁操作并随之进行内存整理。
JIT是Just-In-Time的缩写,也就是即时编译器。JIT平时负责把Class Loader装载到内存中的中间语言代码再进行一次编译,根据目前代码执行的路径、操作系统、硬件情况等编译出最适合当前计算机执行的高效汇编代码,是保障.NET Core应用程序正确运行的重要组件。JIT不是C#语言的编译器,而是中间语言IL的编译器。
Exception Handler的主要作用是处理.NET Core代码在运行过程中产生的异常。如果开发者在代码可能发生异常的地方使用了try-catch段,那么Exception Handler会保证异常对被恰当的catch段处理。如果没有catch段的代码,Exception Handler会把异常对象交给操作系统进行处理。
2.CoreFx项目介绍
CoreFx项目以前又被称为基础类库项目BCL(Basic Class Library)。它完全由C#语言写成,是.NET Core可以提供给开发者的库函数项目。CoreFx项目的绝大多数代码也由.NET Framework的基础类库项目迁移而来。这种代码迁移不是简单的复制,而是针对.NET Core跨平台的特性对Linux、macOS和UNIX做了大量的兼容性调整。
在CoreFx中为了兼容多个操作系统平台,C#的partial关键字得到了大量的应用。对于需要进行跨平台兼容的CoreFx类型,都是通过partial关键字来声明,将多平台公用的代码放在一个源代码文件中,具体某个操作系统相关的代码放在另一个平台相关的源代码文件中。通过partial关键字和条件编译的方法,避免了大量的适配器模式在源代码中的应用,也同时提升了CoreFx类库的执行效率。
CoreFx类库同时也针对.NET Standard标准做出了多方面的调整,.NET Core开发团队的工程师重新审查了.NET Framework类库中的类型以及它们所属的方法,为了兼容.NET Standard标准进行了大量的修改。
3.CLI项目介绍
CLI是Command-Line Interface的缩写,这个项目是.NET Core命令行工具项目。以前的.NET Framework专注于Windows平台。所以很多工具和使用场景在创建时根本没有考虑到对跨平台的支持。这包括一些工具是基于Windows 32 GUI的,无法支持Linux的文件系统和可执行文件格式ELF等。
在明确.NET Core需要支持跨平台这一特性之后,以前在Windows上的工具全都要废弃重来。如何创建一个统一、高效,便于使用的.NET Core工具来支持.NET Core应用程序在多个操作系统上运行就成了一个非常迫切的需求。
设计这样一款工具是非常不容易的,反过来想,如果这很容易,也就不必单独创建一个很大的代码仓库了。另一个很有难度的地方是:.NET Core编译生成的二进制到底是针对不同的操作系统生成不同的文件格式,还是统一的文件格式?最终,.NET Core选择了后者。也就是说,无论是Windows还是Linux,.NET Core编译出来的二进制文件都是以.dll为扩展名的PE格式文件。这就意味着.NET Core需要提供一个容器,来保证在所有操作系统平台上都可以加载PE格式的.dll文件。
CLI项目在.NET的早期也是几经周折,先是多个工具,开发语言也不统一。逐渐地,在.NET Core 2.0预览版中CLI项目的大概样子才固定了下来:创建了一个集项目文件管理、项目构建和代码运行的容器等功能于一身的,名为dotnet的命令行工具。
目前与.NET Core交互的所有操作都需要通过dotnet命令行工具来实现。
4.Roslyn项目介绍
Roslyn是微软为了更好地支持.NET上的高级编程语言而创建的新一代语言编译器。Roslyn并不是仅仅支持C#,VB.NET和F#也同时支持。Roslyn其实是被微软定义为下一代编译平台,而不再只是编译器。因为除了代码编译以外,Roslyn还提供了代码分析服务,以及丰富的API。这使得开发者可以直接使用Roslyn的编译、代码分析等功能创建与提升代码质量相关的应用。
Roslyn除了高度的开放之外,还具有更好的编译效率。相比之前的C #编译器csc.exe,Roslyn生成的中间语言代码(IL)更加高效,编译时间也大大缩短。
目前Visual Studio 2017的代码编辑功能后面全面集成了Roslyn的动态编译功能,在开发人员敲完代码的那一刻,Roslyn马上就可以告诉Visual Studio这一行代码是否有语法错误,引用了哪些其他类型的方法以及被哪些类型引用的信息。Visual Studio就会立刻在图形化的编辑环境提示开发者。
以上是.NET Core的最核心的四个开源项目。这些开源项目都可以在Github的.NET基金会组织下找到,地址是:http://www.github.com/dotnet。
有兴趣的读者可以登录Github网站查看相关源代码仓库,学习以及追踪最新进展。在本书的下一章将主要介绍如何编译.NET Core的主要项目,因为这也是开始.NET Core应用程序调试的基础。
5.关于ASP.NET Core
谈.NET Core也就必须说一下ASP.NET Core。从本质上说,ASP.NET Core和.NET Core是两个相对独立的技术栈。因为ASP.NET Core既可以运行在Windows操作系统的.NET Framework上面,又可以运行在支持跨平台的.NET Core上,也可以运行在.NET另一个著名开源项目Mono上,并没有绝对地依赖哪个.NET框架。
从另一方面说,ASP.NET MVC5改名为ASP.NET Core,也是表明ASP.NET Core会像.NET Core一样支持跨平台。其实,在开源方面,ASP.NET Core是走在前面的。.NET基金会还没有决定把.NET Core开源并且放到Github上时,ASP.NET Core的前身ASP.NET MVC就已经在微软的CodePlex网站上开源了。在那时候,.NET的开源项目Mono可以支持ASP.NET在Linux加Mono的环境下运行ASP.NET Web网站应用程序。现在Mono也开始纳入并支持.NET Standard了,这就意味着今后的日子里,ASP .NET Core即使在Linux操作系统上也保证至少有两个运行时可以选择:.NET Core和Mono。
ASP.NET Core在Github上是一个独立的组织,ASP.NET Core的全部代码仓库都在http://www.github.com/aspnet组织下面。