当前位置: 首页 > news >正文

HybirdCLR 探索—— .NET相关概念(基础)

最新打算研究一下 HybirdCLR,但很明显,不先搞清.NET 相关概念是不行的
(如果连CLR是啥都闹不懂,意味着只能在使用层走马观花...)。
之前,只是零碎地在网上查找过一些术语名词,并没有理解深刻,当然也没记住多少。
这几天(五六个日夜)理解和整理下来,还是感到有些头疼,原因是:
    名词、内容众多;
    官方中文文档生硬的翻译,存在差错/歧义/误差;
    网上他人的文章理解上存在差错/歧义/误差;
    同一个名词出现在不同处有不同的侧重点;
    一个零散的名词描述难以厘清其在整个系统中的位置和作用。
    由于.NET Core的改名 .NET平台 与 .NET 5+实现 从名称上容易混淆。

一、什么是 .NET 平台

.NET: 一个免费开源的、跨语言、跨平台的开发者平台。用来构建不同类型应用程序。其生态包括 集成开发环境(Visual Studio)、技术框架/库、NuGet包管理器、社区论坛、服务支持等。

跨语言:语言无需关心.NET实现,只要使用面向.NET平台的编程语言(可编译为 IL)(如C#、VB、C++等)编写代码,就可以无缝与其他语言互操作(如:A打成Dll后可以直接在B中调用A的方法)。

跨平台:代码经过一次编译,就可运行在任意有.NET框架实现(主要是运行时)的平台上,既不依赖操作系统,也不依赖硬件环境。

当人们还在争论什么语言更好的时候,微软让你看到.NET平台才是重点,C#也只是为宣传.NET而生。从中可见微软的强大与野心。


二、.NET 开发和运行环境

.NET IDE(集成开发环境) = .NET SDK + 代码编辑器 + 调试器 + 图形用户界面。

.NET SDK(软件开发工具包) = Build Engine(构建引擎(如MSBuild)) + Compiler(语言编译器(如Roslyn...)) + .NET CLI(命令行接口工具) + .NET Runtime。

.NET Runtime(程序运行环境) = CLR(公共语言运行时(程序运行虚拟机)) + BCL(基础类库(程序运行时必须依赖的库))。

这里的包含关系和Java体系几乎完全一样,如图:

部分重要关键词详解:

1、.NET CLI(Command-Line Interface)(命令行接口工具)。

 CLI 最终调用的是 Build Engine(构建引擎(如MSBuild))和 Compiler(语言编译器)。
(CLI 可看作为这两者的外观接口)。其命令的结构/格式为: 

donet commondXXX argumentsXXX/optionsXXX

"dotnet" 为驱动程序,最终实际调用的是.NET SDK安装目录下的 dotnet.exe(windows下)。
"commondXXX" 为具体命令。
"argumentsXXX" 为被调用的命令的参数。
"optionsXXX" 为被调用命令的选项。

命令包含:
    ⑴、基本命令:new、restore、build、publish、run、test、vstest、pack、migrate、clean、sln、help、store。
    ⑵、项目修改命令:add package、add reference、remove package、remove reference、list reference。
    ⑶、高级命令:nuget delete、nuget locals、nuget push、msbuild、dotnet install script。
    ⑷、工具管理命令:tool install、tool list、tool update、tool restore(自 .NET Core SDK 3.0 起可用)、tool run(自 .NET Core SDK 3.0 起可用)、tool uninstall。

    可以看出:.NET CLI 囊括了所有操作项目相关的命令
    需要注意:对项目的操作直接用命令行操作即可;如果在 IDE(如 VS)用户界面上进行项目操作,最终也是调用的这些命令

    -------------------------------- NRatel 割 --------------------------------

    注意区分另一个缩写相同的名词!!!
    CLI(Common Language Infrastructure)(公共语言基础结构)。
    它是一个包含:CLR、BCL、CTS、CLS、CIL、元数据等规范的国际性标准。
    (后面后对这些内容进行介绍)

2、CLR(Common Language Runtime)(公共语言运行时)。

    可以理解为:不同语言(面向.NET平台的程序语言)公用或通用的运行时环境

    CLR 是一个泛称,其在不同的.NET实现中有不同的实现。

    CLR 在设计上支持跨平台,但其具体实现也可以只针对某1个特定平台。如:
        .NET Framework 的 CLR 是 .NET Framework CLR(Desktop CLR)(仅支持Windows桌面);
        .NET 5(和 .NET Core)及更高版本的 CLR 是 Core CLR(跨平台); 
        Mono 的 CLR 是 Mono CLR(跨平台)。

    基本功能/优点包括:
        ⑴、性能得到了改进。
        ⑵、能够轻松使用用其他语言开发的组件。
        ⑶、类库提供的可扩展类型。
        ⑷、语言功能,如面向对象的编程的继承、接口和重载。
        ⑸、允许创建多线程的可缩放应用程序的显式自由线程处理支持。
        ⑹、结构化异常处理支持。
        ⑺、自定义特性支持。
        ⑻、垃圾回收。
        ⑼、使用委托取代函数指针,从而增强了类型安全和安全性。 有关委派的详细信息,请参阅通用类型系统。
        
    CLR 有时也被称为“托管”运行时,因为它使用垃圾回收器进行内存管理,还因为它强制执行类型和内存安全。
    CLR 虚拟化(或抽象)了各种操作系统和硬件概念,例如内存、线程和异常(虚拟机无疑)。
    CLR 不仅可执行应用,还可使用 JIT 编译器快速生成和编译代码。
    CLR 为调试器、转储和跟踪工具以及可观测性公开各种诊断服务和 API。
    CLR 通过结合使用 P/Invoke、值类型以及跨本机/托管代码边界对值进行 blit 的功能,提供低级别的 C 样式互操作功能。

3、BCL(Base Class Library)(基础类库/运行时库)。

    可以理解为:应用程序在运行时必须依赖的库,也被称为 框架库、核心.NET 库。

    BCL 是一个泛称,其在不同的.NET实现中有不同的实现。如:
        .NET Framework 的 BCL 是 .NET Framework BCL;
        .NET 5(和 .NET Core)及更高版本的 BCL 可视为 .NET Framework BCL 源码的一个分支。源码:https://github.com/dotnet/runtime/tree/main/src/libraries
        Mono 的 BCL ?

    BCL 包含全部 System.* 命名空间 和 部分 Microsoft.* 命名空间。

-------------------------------- NRatel 割 --------------------------------

.NET 提供了 SDK 和 Runtime 供 开发者/用户下载,(注意,这是 .NET 5(和 .NET Core)系列各版本的实现)
下载地址:https://dotnet.microsoft.com/en-us/download/dotnet。

很明显,
对于开发者,应该下载SDK(SDK包含Runtime)(开发时也需要运行调试);
对于只想单纯运行应用的用户,应该下载Runtime。


三、.NET 多语言开发条件

面向 .NET 的程序语言最终都会被编译为 IL(中间语言)。
这样,就可以让开发者用自己擅长的语言编程,并支持不同语言互操作。
很明显,需要满足一个条件:遵循同一套规则和标准。
由此产生了两个术语:

1、 CTS(Common Type System)(公共类型系统)。

    CTS 是语言可与其他语言 “透明地完成” 跨语言互操作的条件。

    功能职责:
        ⑴、建立一个支持跨语言集成、类型安全和高性能代码执行的框架。
        ⑵、提供一个支持完整实现多种编程语言的面向对象的模型。
        ⑶、定义各语言必须遵守的规则,有助于确保用不同语言编写的对象能够交互作用(CLS)。
        ⑷、提供包含应用程序开发中使用的基元数据类型(如Boolean、Byte、Char、Int32 和 UInt64)的库。

    定义内容:
        CTS 定义的、应支持的两种主要类型:引用和值类型。
        CTS 定义的多个类型类别:类、结构、枚举、接口、委托。
        CTS 还定义类型的相关属性应满足的原则或应具备的特征,包括:特性、可访问性、名称、基类、实现的接口、成员(字段、属性、方法、构造函数、事件、嵌套类型)、继承、重写、隐藏成员等。

    (官方CTS介绍: https://docs.microsoft.com/zh-cn/dotnet/standard/common-type-system)

2、 CLS(Common Language Specification)(公共语言规范)。

    CLS 是 CTS 的子集。

    CLS 是语言可与其他语言 “正常完成” 跨语言互操作的条件。(可以认为是不同语言进行交互最低要求)

    很容易理解:如果不使用反射等非透明方式,“跨语言互操作性” 只需关心公开的、可被其它程序集访问的成员(如public、继承的protected),因为这些足以完成交互
    而对于内部成员(如Private、internal)则无需关心。

    规范内容包括:类型和类型成员签名、命名约定、类型转换、数组、接口、枚举、类型成员概述、成员可访问性、泛型类型和成员、构造函数、属性、事件、重载、异常、特性等。

   (官方CLS介绍:https://learn.microsoft.com/zh-cn/dotnet/standard/language-independence)

3、 CTS、CLS 及语言的关系。

四、.NET 跨平台运行原理(托管执行过程)

托管的执行过程包括以下步骤:

1、选择编译器。

    若要获取公共语言运行时提供的好处。
    开发者必须选择一个或多个面向CLR的程序语言和对应的语言编译器
    
2、将代码编译为 MSIL。

    编译器会将源代码转换为托管模块(Managed Module)。   
    托管模块是一个可移植执行体文件(基于 Microsoft PE 和 用于可执行内容的通用对象文件格式 COFF)。
    托管模块主要包含 MSIL(中间语言)、元数据。
    托管模块还包含 PE32或PE32+头、CLR 头。
    托管模块需要 CLR 才能执行。

    CLR 实际不和托管模块工作,它和程序集工作。

    编译器会默认将生成的托管模块转换为程序集。
    对于C#编译器,生成的程序集是含有清单的托管模块。
    清单指出程序集只由一个文件构成(这个文件就是托管模块,没有其他资源)(清单上不记录清单自身)。

3、将 MSIL 编译为 本机代码。

    编译器会将 MSIL 转换为特定 CPU 架构(比如 X86、X64、Arm64)的本机代码。
    .NET 支持两种编译模型:AOT(预编译/提前编译)和 JIT(实时编译)。
    在 Android、Linux、macOS 和 Linux 上,JIT 编译是默认的,AOT 是可选的(例如,使用 ReadyToRun)。
    在 iOS 上,除非在模拟器中运行,否则 AOT 是必需的。
    在 WebAssembly (Wasm) 环境中,AOT 是必需的。

    JIT 编译,注意:

        ⑴、如果托管代码调用特定于平台的本机 API 或特定于平台的类库,它将仅在该操作系统上运行。(由于平台差异,并不是完全无脑跨平台)
        ⑵、JIT 考虑到 某些代码可能在运行期间永远都不会被调用,所以它只将执行期间用到的 MSIL转换为本机代码。(按需转换,节省时间和内存)
        ⑶、JIT 会在内存中存储生成的本机代码,以便被该进程上下文中的后续调用访问。(缓存结果,避免重复转换)

    AOT 编译:

        可以使用 Ngen.exe(本机映像生成器)将 MSIL 程序集预编译成本机代码。
    预编译(运行前)的好处是:
        ⑴、可以避免运行时编译对性能产生负面影响。(大多数情况下可忽略)
        ⑵、使本机代码可以在进程之间进行共享。(主要)
    它一次编译整个程序集,而不是一次编译一种方法。
    它将本机映像缓存中生成的代码作为磁盘上的文件保存。

    -------------------------------- NRatel 割 --------------------------------

    在编译期间,代码必须通过检查 MSIL 和 元数据 的验证过程以查明是否可以将代码确定为类型安全。
    (确认代码可以访问内存位置,并仅通过正确定义的类型调用方法)
    运行时以下语句作为 “类型安全” 的标准:
        ⑴、对类型的引用严格符合所引用的类型。
        ⑵、在对象上只调用正确定义的操作。
        ⑶、标识与声称的要求一致。

4、运行代码。

    CLR 提供了 支持进行托管执行的基础结构 和 可在执行期间使用的服务。
    在运行方法之前,必须将其编译为特定于处理器的代码。
    每个生成了 MSIL 的方法在第一次调用时都被 JIT 编译,然后运行。(编译一次后缓存)
    下次运行该方法时,将运行现有的 JIT 编译的本机代码。
    JIT 编译和运行代码的过程是重复的,直到执行完成。  
    
    在执行期间,托管代码会接受服务(托管代码会享受到 CLR 提供的一些服务)
    如:垃圾收集、安全性、与非托管代码的互操作性、跨语言调试支持、增强部署 和 版本控制支持。

部分重要关键词详解:

1、MSIL (Microsoft Intermediate Language) (中间语言)

    IL 又被称为 IL 或 CIL(Common IL)。
    IL 是一组独立于 CPU 且可以有效地转换为本机代码的说明(不能直接被执行)(通常由 JIT 编译器进行转换)。
    它是一种紧凑的代码格式,可在任何操作系统或体系结构上受到支持。 
    CLR 为不同 CPU 架构提供一个或多个 JIT 编译器,所以同一组的 MSIL 可以在任何受支持的 CPU 架构上进行 JIT 编译和运行。
    MSIL 包括有关加载、存储、初始化和调用对象方法的说明;
    以及有关算术和逻辑运算、控制流、直接内存访问、异常处理和其他操作的说明。

2、元数据(Metadata)

    简单说,元数据就是一个数据表集合。
    一些数据表描述了模块中定义了什么(每种类型的定义、每种类型的成员的签名)
    另一些描述了模块引用了什么(代码引用的成员、CLR在执行期间引用的其他数据)

    元数据和它描述的 MSIL 使代码能够描述自身,这意味着将不需要类型库或接口定义语言 (IDL)。
    CLR 在执行期间会根据需要从文件中查找并提取元数据。

    元数据的用途(部分):
    ⑴、元数据避免了编译时对原生C/C++头和库文件的需求,因为元数据中已经包含了有关引用类型/成员的全部信息。
    ⑵、VS 用元数据帮助你写代码。“只能感知”技术会解析元数据,告诉你一个类型提供了那些方法、属性、事件和字段,对于方法还能告诉你需要的参数。
    ⑶、CLR 的代码验证过程使用元数据确保代码只执行“类型安全”的操作。
    ⑷、元数据允许将对象的字段序列化到内存块,将其发送给另一台机器,然后反序列化,在远程机器上重建对象状态。
    ⑸、元数据允许垃圾回收期跟踪对象生存期。垃圾回收期能判断任何对象的类型,并从元数据中知道哪个对象中的哪个字段引用了其他对象。

3、程序集(Assembly)

    抽象地说,程序集是一个或多个模块/资源文件的逻辑性分组。
    具体地说,程序集是一个个或多个类型定义文件及资源文件的集合。
    在程序集的所有文件中有一个文件容纳了清单,清单也是一个元数据集合,表中主要包含作为程序集组成部分的那些文件的名称。
    此外,清单还描述了程序集的版本、语言文件、发布者、公开导出的类型以及构成程序集的所有文件。

    CLR 操作的是程序集。
    换言之,CLR总是首先加载包含 “清单” 元数据的文件,再根据 “清单” 来获取程序集找那个的其他文件的名称。

    程序集是 .dll 或 .exe 文件
    程序集对外提供一组可由应用程序或其他程序集调用的 API 。
    程序集可以包括接口、类、结构、枚举和委托等类型。
    有时,项目的 bin 文件夹中的程序集被称为二进制文件。

    程序集是重用、安全性以及版本控制的最小单元。
    程序集既是单文件的,也可以是多文件的(这取决于生成它的编译器或工具)。

4、本机代码(Native Code)

    本机代码即 机器码 或 机器指令码。
    机器指令码是计算机(CPU)直接使用(理解并直接执行)的字节码指令代码(一组二进制数,全部由0和1组成)。

5、JIT(Just In Time)(实时编译器)

    与 AOT 类似的是,它们都将IL转换为处理器可以理解的机器代码。 
    与 AOT 不同的是,JIT编译是在应用程序执行时按需进行的,并且是在同一台机器上执行的。 
    因为 JIT 编译发生在应用程序执行期间,所以编译时间是运行时间的一部分。(JIT 方式实际运行时长 = 代码编译时长 + 代码执行时长)
    因此,JIT 编译器需要去考虑/平衡:节省代码编译时长,还是节省代码执行时长?(要使总时长最短)。
    但优点是,JIT 了解实际的硬件,可以使开发人员不必交付不同的实现。(节省硬盘空间) 

6、AOT(Ahead Of Time)(预编译器)

    与 JIT 类似的是,它们都将IL转换为处理器可以理解的机器代码。 
    与 JIT 不同的是,AOT 编译是在应用程序执行前进行的,并且通常是在不同计算机上执行的。
    AOT 工具链不会在运行时进行编译,因此它们不需要最大程度地减少编译所花费的时间。(AOT = 代码执行时长)
    这意味着它们可花更多的时间进行优化。(可以在编译时用不计成本的时间来生成运行时最优、最省时的机器码)
    由于 AOT 的上下文是整个应用程序,因此 AOT 编译器还会执行跨模块链接和全程序分析,这意味着之后会进行所有引用并会生成单个可执行文件。

五、.NET实现

1、什么是 .NET实现?

.NET 是跨平台的。但一些应用程序只需要运行在确定的一个或多个平台上。
比如,桌面应用程序只需要运行在桌面设备和系统上(Windows桌面、Linux、Mac);移动应用程序只需要运行在移动设备和系统上(Android、IOS)。
另外,还有一些非技术的历史原因:微软早年只希望针对 Windows 平台做一个实现(.NET Framework)。

那么,我个人理解 .NET实现就是:为特定平台提供运行时环境和开发环境的框架的技术方案。

.NET 的每个实现都具有以下组件:
    ⑴、一个或多个运行虚拟器 CLR。例如 .NET Framework CLR 和 .NET 5 的 Core CLR。
    ⑵、一个运行时库 BCL。例如 .NET Framework 的 BCL 和 .NET 5 BCL。
    ⑶、(可选)一个或多个应用程序框架。例如 .NET Framework 和 .NET 5+ 中 都包含 ASP.NET、Windows Forms 和 WPF。
    ⑷、可以包含开发工具。某些开发工具在多个实现之间共享。

Microsoft 目前支持以下四种 .NET 实现各有平台侧重,各有建立其上的应用程序框架):
    ⑴、.NET 5(和 .NET Core)及更高版本:
        官方最新的、跨平台的.NET实现,专用于处理大规模的服务器和云工作负载。
        还支持桌面应用(Windows、macOS 和 Linux)运行。
        使用的应用程序框架有:ASP.NET、Windows Forms 和 WPF等
    ⑵、.NET Framework:
        官方早期的、针对 Windows桌面的.NET实现。
        使用的应用程序框架有:ASP.NET、Windows Forms 和 WPF等。
    ⑶、Mono:
        针对小型运行时(Android、macOS、iOS、tvOS、watchOS等)的、跨平台的.NET实现。
        使用的应用程序框架为:Xamarin。
        Mono 还支持 Unity 引擎生成的游戏。
    ⑷、UWP:
        用于为物联网 (IoT) 生成新式触控 Windows 应用程序和软件的.NET实现。

2、.NET Standard

⑴、什么是.NET Standard?

    .NET Standard 是针对多个 .NET 实现推出的一套正式的 .NET API 规范(不同 BCL 的标准)
    推出 .NET Standard 的背后动机是要提高 .NET 生态系统中的一致性。 

    .NET 5 及更高版本采用不同的方法来建立一致性,大多数情况下都不再需要 .NET Standard,故不再发布更新版本的 .NET Standard。(不再更新)
    但会继续支持 .NET Standard 2.1 及更早版本。(但未废弃)
    如果要在 .NET Framework 和其他任何 .NET 实现(例如 .NET Core)之间共享代码,则库必须面向 .NET Standard 2.0。(.NET Framework 不支持.NET Standard 2.1)

⑵、.NET Standard 版本及选择

    已对 .NET Standard 进行版本控制。 每个新版本都会添加更多 API。
    当库是针对 .NET Standard 的某个版本生成时,它可以在任何实现该版本(或更高版本)的 .NET Standard 的 .NET 实现上运行。
    面向更高版本的 .NET Standard让库能够使用更多 API,但这意味着它只能在较新版本的 .NET 上使用。
    面向较低版本会减少可用的 API,但意味着库可以在更多位置运行。

    .NET 实现 可能会同时支持多个版本的 .NET Standard,可以视情况进行选择。

⑶、.NET Standard 的问题

    ①、添加新 API 的速度缓慢。(.NET5本身是代码基底共享的,不需要等待标准制定)
    ②、复杂的版本控制。(.NET5使用 “TFM 命名约定” 解决这个问题)
    ③、运行时出现不受平台支持的异常。(.NET5使用 “平台兼容性分析器” 解决这个问题)

3、.NET 实现的历史及未来趋势

2002 年,Microsoft 发布了 .NET Framework,这是用于创建 Windows 应用的开发平台。 目前 .NET Framework 的版本为 4.8,并且仍由 Microsoft 支持。
2004 年,Xamarin公司(先前是Novell,最早为Ximian) 发布了 Mono。
2014 年,Microsoft 推出了 .NET Core 作为 .NET Framework 的跨平台开源后续产品。 这种新的 .NET 实现在版本 3.1 中一直保持 .NET Core 的名称。 
2020 年,Microsoft 将 .NET Core 3.1 之后的下一个版本命名为 .NET 5。
    跳过版本编号 4.x,是为了避免与 .NET Framework 4.x 混淆。
    从名称中删除了“Core”,是为了强调这是 .NET 未来的主要实现。
    与 .NET Core 或 .NET Framework 相比,.NET 5 会支持类型更多的应用和平台。
2021 年,Microsoft 发布了 .NET 6 (作为 .NET5+ 的首个LTS版本)。
    .NET 6 提供 .NET 统一计划的最终部分,该计划在 .NET 5 中启动。
    .NET 6 在移动、桌面、IoT 和云应用之间统一了 SDK、基础库和运行时。

.NET5+ 让 .NET Core、.NET Framework 和 Mono(Xamarin)等走向统一,
并且打通七大开发方向(桌面应用、Web应用、云服务、移动开发、游戏开发、物联网IoT、人工智能AI)。

前后对比(如图):

怎么理解统一?

⑴、唯一的 .NET 实现。
⑵、唯一的 SDK。
⑶、唯一/唯二的 CLR:CoreCLR 和 MonoCLR 无缝替换(未来可能统一为CoreCLR)。
⑷、唯一的 BCL:整合。
⑸、多个上层应用程序框架。

六、.NET 应用发布

1、发布时可指定 独立运行/依赖框架

    独立运行:包含运行时、运行时库、应用本身和第三方依赖项。
    依赖框架:只包含应用本身和第三方依赖项。(没有运行时,只能依赖框架运行)

2、发布时可指定发布的结果

    应用:分为 不跨平台的可执行文件 和 跨平台应用程序。
    可执行文件:不跨平台,它们特定于操作系统和 CPU 体系结构。
    二进制文件(主要应该是指Dll文件):可在安装了目标.NET运行时的任何操作系统上运行。

3、发布时,可指定平台或默认为当前平台

注意,“是否可运行” 与 “应用框架、发布结果、平台、运行时” 均相关:

    得让 “支持某平台的应用框架开发的应用” 跑在 “支持该平台的运行时” 中。
    得让 “可执行文件” 跑在 对应平台的操作系统上。
    得让 “二进制文件” 运行在 目标.NET运行时中(这是跨平台的)

七、应关心的重点

说了这么多内容,回归本题:

1、对于 Unity,代码最终都被打包为 Dll文件(可以将发布结果视为 二进制文件),然后交给 Mono 或 IL2CPP执行。
    所以,Unity开发者关心的重点在于 Mono 和 IL2CPP 如果解析运行 DLL文件。
    其中,Mono 解析运行 Dll文件的过程就是本文中的 “托管运行过程”。

2、Unity 目前使用 Mono 和 IL2CPP,未来会是 CoreCLR。
     .NET和Unity的未来,让用户编写高性能代码,并带来长期的稳定性与兼容性

3、要研究 HybirdCLR,还需更深入了解 CLR 和 IL2CPP。
     继续加油!

八、参考

.NET 文档 | Microsoft Learn

.NET 术语表 | Microsoft Learn

.NET(和 .NET Core)- 简介和概述 | Microsoft Learn

.NET SDK 概述 | Microsoft Learn

.NET Downloads (Linux, macOS, and Windows)

.NET CLI | Microsoft Learn

公共语言运行时 (CLR) 概述 - .NET | Microsoft Learn

托管执行过程 | Microsoft Learn

运行时库概述 | Microsoft Learn

常规类型系统和公共语言规范 | Microsoft Learn

.NET Platform

.NET Blog

Introducing .NET 5 - .NET Blog

Documentation | Mono

Unity Future .NET Development Status - Unity Forum

《CLR via C# 第四版》

以及其他一些网上的文章和讨论

相关文章:

  • Linux篇【1】:入门与基本指令详解(中)
  • 基于强化学习PPO(Proximal Policy Optimization)算法的无人机姿态控制系统
  • HDFS源码分析——NameNode启动流程
  • 【Day20】LeetCode算法题【1784. 检查二进制字符串字段】【14. 最长公共前缀】
  • 状态反馈镇定之非线性系统反馈线性化
  • 【408计算机组成原理】—加减运算和溢出判断(八)
  • vue3 setup的四点注意
  • Python 输入与输出
  • 基于JAVA校园租赁系统的设计与实现计算机毕业设计源码+系统+数据库+lw文档+部署
  • 【Linux初阶】从0到1带你用云服务器搭建Linux环境
  • Kubernetes技术与架构-10
  • 基于微信小程序云开(统计学生信息并导出excel)3.0版
  • 【JAVAEE框架】浅谈 AOP 及代码实现
  • React获取DOM和获取组件实例的方式
  • [Spark、hadoop]spark Streaming的核心DStream
  • dva中组件的懒加载
  • Essential Studio for ASP.NET Web Forms 2017 v2,新增自定义树形网格工具栏
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Linux编程学习笔记 | Linux IO学习[1] - 文件IO
  • MyEclipse 8.0 GA 搭建 Struts2 + Spring2 + Hibernate3 (测试)
  • 给初学者:JavaScript 中数组操作注意点
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 简单基于spring的redis配置(单机和集群模式)
  • 前端学习笔记之观察者模式
  • 悄悄地说一个bug
  • 入门到放弃node系列之Hello Word篇
  • ​马来语翻译中文去哪比较好?
  • ()、[]、{}、(())、[[]]命令替换
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (c语言)strcpy函数用法
  • (python)数据结构---字典
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)ssm户外用品商城 毕业设计 112346
  • (南京观海微电子)——COF介绍
  • (篇九)MySQL常用内置函数
  • (三)elasticsearch 源码之启动流程分析
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (原创) cocos2dx使用Curl连接网络(客户端)
  • (转)IOS中获取各种文件的目录路径的方法
  • **PHP二维数组遍历时同时赋值
  • .gitattributes 文件
  • .Net Framework 4.x 程序到底运行在哪个 CLR 版本之上
  • .Net 路由处理厉害了
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .net 桌面开发 运行一阵子就自动关闭_聊城旋转门家用价格大约是多少,全自动旋转门,期待合作...
  • .Net的DataSet直接与SQL2005交互
  • /var/spool/postfix/maildrop 下有大量文件
  • [ C++ ] STL_stack(栈)queue(队列)使用及其重要接口模拟实现
  • [ vulhub漏洞复现篇 ] Apache APISIX 默认密钥漏洞 CVE-2020-13945
  • [1204 寻找子串位置] 解题报告
  • [20171101]rman to destination.txt
  • [20171113]修改表结构删除列相关问题4.txt
  • [BUUCTF]-PWN:[极客大挑战 2019]Not Bad解析
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强