学习体系结构 - AArch64内存管理

学习体系结构 - AArch64内存管理

Learn the architecture - AArch64 memory

management

Version 1.2

个人的英语很一般,对拿不准的翻译校准在后面添加了英文原文。

1、 概述

本指南介绍了AArch64中的内存转换,这是内存管理的关键。它解释了如何将虚拟地址转换为物理地址转换表格式,以及软件如何管理转 换转译后备缓冲器(TLB)

这些信息对于任何正在开发底层代码的人都很有用,比如启动代码或驱动程序。它与任何正在编写设置或管理内存管理单元(MMU)代码的人特别相关。

在本指南的最后,您可以检查您的知识。您将了解如何将虚拟地址转换为物理地址。您将能够命名不同的地址空间,并描述地址空间如何映射到翻译的各个阶段。您还将了解软件何时必须执行TLB维护,以及TLB维护命令的语法。

2、 什么是内存管理?

内存管理描述了如何控制对系统中内存的访问。每次操作系统或应用程序访问内存时,硬件都会执行内存管理。内存管理是一种为应用程序动态分配内存区域的方法。

为什么需要内存管理?

应用程序处理器被设计为运行一个丰富的操作系统,如Linux,并支持虚拟内存系统。在处理器上执行的软件只能看到虚拟地址,而处理器会将其转换为物理地址。这些物理地址被呈现给内存系统,并指向内存中的实际物理位置。

3、虚拟地址和物理地址

使用虚拟地址的好处是,它允许管理软件,如操作系统(OS),来控制呈现给软件的内存的视图。操作系统可以控制什么内存是可见的,该内存是可见的虚拟地址,以及允许对该内存的访问。这允许操作系统能够对应用程序沙盒化(从另一个应用程序中隐藏一个应用程序的资源),并提供来自底层硬件的抽象。

使用虚拟地址的一个好处是,操作系统可以将内存的多个碎片物理区域作为单个连续的虚拟地址空间呈现给应用程序。

虚拟地址也有利于软件开发人员,他们在编写应用程序时将不知道系统的确切内存地址。有了虚拟地址,软件开发人员就不需要关心物理内存了。应用程序知道,应该由操作系统和硬件一起工作执行地址转换。

事实上,每个应用程序都可以使用自己的一组虚拟地址,这些地址将映射到物理系统中的不同位置。随着操作系统在不同的应用程序之间切换时,它会重新编程映射关系。这意味着当前应用程序的虚拟地址将映射到内存中正确的物理位置。虚拟地址通过映射被转换为物理地址。虚拟地址和物理地址之间的映射存储在转换表(有时也称为页表)中,如下图所示:

在这里插入图片描述

转换表在内存中,由软件管理,通常是操作系统或管理程序。翻译表不是静态的,这些表可以根据软件更改的需要进行更新。这将更改虚拟地址和物理地址之间的映射。

4、内存管理单元(MMU)

内存管理单元(MMU)负责将软件使用的虚拟地址转换为内存系统中使用的物理地址。

MMU包含以下内容:

  • 表行走单元(The table walk unit),它包含从内存中读取转换表的逻辑
  • 翻译后备缓冲区(TLBs),它缓存最近使用的翻译

由软件发布的所有内存地址都是虚拟的。这些内存地址被传递给MMU,MMU检查TLB是否有最近使用的缓存转换。如果MMU没有找到最近缓存的转换,表行走单元将从内存中读取适当的表项或条目,如下所示:

在这里插入图片描述

在进行内存访问之前,一个虚拟地址必须被转换为一个物理地址(因为我们必须知道我们正在访问的是哪个物理内存位置)。这种转换的需求也适用于缓存的数据,因为在Armv6和更高版本的处理器上,数据缓存使用物理地址(经过物理标记的地址)来存储数据。因此,在完成缓存查找之前,必须转换地址。

架构是一种行为规范。缓存的行为必须好像它们具有物理标记。实现可能采用不同的方法,只要这不是软件可见的。

表项(Table Entry)

转换表的工作原理是将虚拟地址空间划分为相同大小的Block,并为每个块在表中提供一个 Entry。

表中的 Entry 0 提供 Block 0 的映射,Entry 1提供 Block1 的映射,以此类推。每个条目包含相应的物理内存块的地址以及访问物理地址时使用的属性。

在这里插入图片描述

表查找(Table look up)

当发生转换时会发生表查找。当发生转换时,软件发出的虚拟地址将被一分为二,如图所示:

在这里插入图片描述

此图显示了一个单级查找。

图中标记为 “Which entry” 的高位告诉您要查看哪个块条目,并且它们被用作表中的索引。此输入块包含该虚拟地址的物理地址。

多级转换(Multilevel translation)

在单层查找中,虚拟地址空间被分割成相同大小的块。事实上,使用表的层次结构。

第一个表(Level 1 table)将虚拟地址空间分成大块。这个表中的每个条目都可以指向一个大小相同的物理内存块,也可以指向另一个表,该表将该块细分为更小的块。我们将这种类型的表称为“多层表”。在这里,我们可以看到一个有三个层次的多级表的例子:

在这里插入图片描述

在Armv8-A中,级别的最大数量是4个,级别编号为0到3。

这种多级方法允许描述更大的块和更小的块。大块和小块的特征如下:

  • 大块比小块需要更少的读取级别来翻译。此外,大块在TLB中缓存更有效
  • 小块给出了软件对内存分配的细粒度控制。然而,小块在TLB中缓存的效率较低。缓存效率低是因为小块需要通过级别进行多次读取才能进行翻译。

为了管理这种权衡,操作系统必须平衡使用较大映射的效率和使用较小映射的灵活性,以获得最佳性能。

处理器在启动表查找时并不知道转换的大小。处理器通过执行表行走来计算正在转换的块的大小。

5、 地址空间

在AArch64中有几个独立的虚拟地址空间。此图显示了这些虚拟地址空间:

在这里插入图片描述

该图显示了三个虚拟地址空间:

  • Non-secure EL0 and EL1
  • Non-secure EL2
  • EL3

每个虚拟地址空间都是独立的,并且都有自己的设置和表。我们经常称这些设置和表为“翻译机制”。 Secure EL0、Secure EL1和Secure EL2也有虚拟地址空间,但它们没有显示在图中。

在Armv8.4-A中添加了对Secure EL2的支持。

因为存在多个虚拟地址空间,所以指定地址所在的地址空间很重要。例如,NS.EL2:0x8000是指在 Non-secure EL2虚拟地址空间中的地址0x8000。

该图还显示了来自 Non-secure EL0和Non-secure EL1的虚拟地址都经过了两组表。这些表支持虚拟化,并允许虚拟机管理程序(hypervisor)虚拟化虚拟机(VM)所看到的物理内存的视图。

Armv9-A支持上述针对Armv8-A的所有虚拟地址空间。Armv9-A引入了可选的领域管理扩展(RME)。当实现RME时,还存在额外的翻译机制:

  • Realm EL1 and EL0
  • Realm EL2 and EL0
  • Realm EL2

在虚拟化中,我们称由操作系统控制的翻译称为Stage 1。Stage 1的表将虚拟地址转换为中间物理地址(IPAs)。在阶段1中,操作系统认为IPA是物理地址空间。然而,管理程序监控程序(hypervisor)控制着第二组翻译,我们称之为Stage 2。这第二组翻译将IPA转换为物理地址。此图显示了这两组翻译的工作原理:

在这里插入图片描述

虽然在表格格式上有一些细微的差异,但Stage 1和Stage 2的翻译过程通常是相同的。

在Arm中,我们在许多示例中都使用了地址0x8000。0x8000也是使用Arm链接器(armlink)进行链接的默认地址。这个地址来自一台早期的微型计算机,BBC Micro Model B,它在地址0x8000处有ROM(和侧面的RAM)。BBC Micro Model B是由一家名为Acorn的公司建造的,该公司开发了Acorn RISC Machine(ARM),后来成为Arm。

物理地址(Physical Addresses)

除了多个虚拟地址空间外,AArch64还具有多个物理地址空间(PAS):

  • Non-secure PAS0
  • Secure PAS
  • Realm PAS
  • Realm PAS(Armv9-A only)
  • Root PAS(Armv9-A only)

虚拟地址可以映射到哪个物理地址空间取决于处理器的当前安全状态。下面的列表显示了安全状态及其对应的虚拟地址映射目标:

  • Non-secure state:虚拟地址只能映射到 Non-scure 的物理地址
  • Secure state:虚拟地址可以映射到 Secure 或 Non-secure 的物理地址
  • Realm state:虚拟地址可以映射到 Realm 或 Non-secure 的物理地址
  • Root state:虚拟地址可以映射到任何物理地址空间。

当处于具有多个物理地址空间可见性的安全状态时,转换表条目控制使用哪个输出的物理地址空间。下图显示了多个物理地址空间的映射:

在这里插入图片描述

地址大小(Address sizes)

AArch64是一个64位的架构,但这并不意味着所有的地址都是64位的。

虚拟地址的大小

虚拟地址以64位的格式存储。因此,加载指令(LDR)和存储指令(STR)中的地址总是在 X寄存器 中指定。然而,并非X寄存器中的所有地址都有效。

此图显示了AArch64中的虚拟地址空间的布局:
在这里插入图片描述

EL0/EL1虚拟地址空间有两个区域:内核空间和应用程序空间。这两个区域显示在图的左侧,内核空间在顶部,应用程序空间被标记为“User Space”,在地址空间的底部。内核空间和用户空间有单独的转换表,这意味着它们的映射可以保持独立。

在所有其他异常级别的地址空间的底部有一个单个区域。这个区域显示在图表的右侧,是一个没有文本的方框。

如果将HCR_EL2.E2H设置为1,则将启用主机操作系统在EL2中运行的配置,以及主机操作系统的应用程序在EL0中运行的配置。在这种情况下,EL2也有一个上区域和一个下区域。

地址空间的每个区域具有可达52位的大小。然而,每个区域都可以独立地缩小到一个更小的尺寸。TCR_ELx寄存器中的TnSZ字段控制着虚拟地址空间的大小。例如,此图显示了TCR_EL1控制EL0/EL1虚拟地址空间:

在这里插入图片描述

虚拟地址大小编码为:

virtual address size in bytes = 264-TCR_ELx.TnSZ

虚拟地址的大小也可以表示为地址位的数量:

Number of address bits = 64 - TnSZ

因此,如果TCR_EL1.SZ1被设置为32,EL0/EL1虚拟地址空间中的内核区域的大小为232字节(0xFFFF_FFFF_0000_0000到0xFFFF_FFFF_FFFF_FFFF)。任何超出配置范围的地址在访问时将产生异常。这种配置的优点是,我们只需要描述尽可能多的地址空间,这就节省了时间和空间。例如,假设OS内核需要1GB的地址空间(30位的地址大小)来实现其内核空间。如果操作系统将T1SZ设置为34,则只创建描述1GB的翻译表条目,如64 - 34 = 30。

所有的Armv8-A实现都支持48位的虚拟地址。支持52位虚拟地址是可选的,并由ID_AA64MMFR2_EL1报告。在编写时,还没有一个Arm Cortex-A处理器支持52位虚拟地址。

物理地址的大小

物理地址的大小是实现定义(IMPLEMENTATION DEFINED)的,最多52位。ID_AA64MMFR0_EL1寄存器报告由处理器实现的大小。对于Arm Cortex-A处理器,这通常是40位或44位。

在Armv8.0-A中,一个物理地址的最大大小是48位。这在Armv8.2-A中被扩展到52位。

中间物理地址的大小

如果您在转换表条目中指定的输出地址大于已实现的最大值,则内存管理单元(MMU)将产生一个异常作为地址大小错误。

IPA空间的大小可以进行与虚拟地址空间相同的配置。VTCR_EL2.T0SZ控制大小。可以配置的最大大小与处理器支持的物理地址大小相同。这意味着您不能配置比所支持的物理地址空间更大的IPA空间。

地址空间标识符 - 使用已拥有的进程来标记翻译

许多现代操作系统的应用程序似乎都运行在同一个地址区域,这就是我们所描述的用户空间。事实上,不同的应用程序需要不同的映射。这意味着,例如,VA 0x8000的翻译取决于当前正在运行的哪个应用程序。

理想情况下,我们希望不同应用程序的翻译在翻译后备缓冲区(TLBs)中共存,以防止在上下文切换上需要TLB失效。但是处理器如何知道要使用哪个版本的VA 0x8000翻译呢?在Armv8-A中,答案是地址空间标识符(ASID)。

对于EL0/EL1虚拟地址空间,可以使用转换表项的属性字段中的nG位将转换标记为全局(G)或非全局(nG)。例如,内核映射是全局翻译,而应用程序映射是非全局翻译。全局翻译应用于当前正在运行的任何应用程序。非全局翻译仅适用于特定的应用程序。

非全局映射在TLB中用ASID进行标记。在TLB查找中,将TLB条目中的ASID与当前选择的ASID进行比较。如果它们不匹配,则不使用该TLB条目。此图显示了内核空间中没有ASID标记的全局映射和用户空间中带有ASID标记的非全局映射:

在这里插入图片描述

该图显示,多个应用程序的TLB条目允许在缓存中共存,并且ASID决定使用哪个条目。

ASID存储在两个TTBRn_EL1寄存器中的一个。TTBR0_EL1通常用于用户空间。因此,单个寄存器更新可以同时更改ASID和它所指向的转换表。

ASID标记也可以在EL2中使用,当HCR_EL2.E2H==1。

虚拟机标识符 - 使用所拥有的虚拟机来标记翻译

EL0/EL1翻译也可以用虚拟机标识符(VMID)进行标记。VMIDs 允许来自不同VM的翻译在缓存中共存。这类似于ASIDs 对翻译来自不同应用程序的工作方式。事实上,这意味着一些翻译将同时被标记为VMID和ASID,并且两者都必须匹配才能使用TLB条目。

当安全状态支持虚拟化时,EL0/EL1翻译总是用VMID标记,即使没有启用Stage 2翻译。这意味着,如果您正在编写初始化代码而没有使用系统管理程序(hypervisor),那么在设置Stage 1 MMU之前设置一个已知的VMID值是很重要的。

通用非私有 Common not Private

如果一个系统包含多个处理器,那么在一个处理器上使用的ASID和VMID在其他处理器上是否具有相同的含义?

对于Armv8.0-A,答案是它们不必意味着相同的东西。不要求软件在多个处理器上以相同的方式使用给定的ASID。例如,ASID 5 可能被一个处理器上的计算器使用,可能被另一个处理器上的web浏览器使用。这意味着由一个处理器创建的 TLB 条目不能被另一个处理器使用。

事实上,软件不太可能在不同的处理器之间使用不同的 ASIDs。软件在给定系统中的所有处理器上以相同的方式使用 ASIDs 和 VMIDs 更为常见。因此,Armv8.2-A在转换表基寄存器(TTBR)中引入了通用非私有(CnP)位。当设置了CnP位时,该软件承诺在所有处理器上以相同的方式使用 ASIDs 和 VMIDs ,这允许由一个处理器创建的 TLB 条目被另一个处理器使用。

我们一直在谈论处理器,但是,从技术上讲,我们应该使用 Process Element(PE)这个术语。PE是对实现Arm架构的任何机器的通用术语。这很重要,因为在处理器之间共享 TLB 是困难的。但是在一个多线程处理器中,每个硬件线程都是一个 PE,它更希望共享 TLB 条目。

6、 控制地址转换和转换表的格式

在这里,我们可以看到翻译表条目所允许的不同格式:

在这里插入图片描述

为了清晰起见,此图没有指定位字段的宽度。您可以在 Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile: The VMSAv8-64 translation table format descriptors 中找到这个信息。

每个条目是64位,底部的两个位决定了条目的类型。

请注意,某些表条目仅在特定的级别上有效。表的最大级别数为4个,这就是为什么没有针对 Level 3(或第四级)表的表描述符的原因。类似地,Level 0中也没有块描述符或页面描述符。因为Level 0条目覆盖了很大的虚拟地址空间区域,所以允许块没有意义。

Levels 0 - 2 的表描述符的编码与 Level 3 的页面描述符相同。这种编码允许“递归表”,它们指向它们自己。这很有用,因为它便于计算特定页表条目的虚拟地址,以便可以更新它。

7、 翻译颗粒

翻译颗粒是可以描述的最小的内存块。没有更小的可以描述,只有更大的块,这是颗粒的倍数。

AArch64支持三种不同的颗粒尺寸: 4KB、16KB和64KB。

处理器所支持的颗粒大小是由 ID_AA64MMFR0_EL1 定义并报告的实现。所有的 Arm Cortex-A 处理器都支持4KB和64KB。所选的颗粒是在最新级别表中可以描述的最小块。也可以描述更大的块。此表显示了基于所选颗粒的每个级别表的不同块大小:

在这里插入图片描述

在引入 Armv9.2-A 和 Armv8.7-A 之前,对使用52位地址有限制。当所选颗粒为4KB或16KB时,最大虚拟地址区域大小为48位。同样地,输出物理地址被限制为48位。只有当使用64KB的颗粒时,才能使用完整的52位。

TCR_EL1 有两个独立的字段来控制内核空间的颗粒大小和用户空间的虚拟地址范围。这些字段对于内核空间称为TG1,对于用户空间称为TG0。程序员面临的一个潜在问题是,这两个字段有不同的编码。

地址转换的起始级别

颗粒和虚拟地址空间的大小一起控制着地址转换的起始级别。

上一个表总结了每级表中每个颗粒的块大小(由单个条目所覆盖的虚拟地址范围的大小)。从块的大小中,您可以计算出虚拟地址的哪些位被用来索引表的每个级别。

让我们以4KB的颗粒为例。此图显示了用于索引一个4KB颗粒的不同级别表的位:

在这里插入图片描述

假设,对于一个配置,您将虚拟地址空间的大小 TCR_ELx.T0SZ 设置为32。然后虚拟地址空间的大小,以地址位计算,计算为:

64-T0SZ = 32 位地址空间(地址位31:0)

如果我们再看前面的4KB颗粒图,Level 0被位 47:39 索引。对于一个32位的地址空间,你就没有这些位了。因此,您的配置的初始转换级别是 Level 1。

接下来,假设您将 T0SZ 设置为 34:

64-T0SZ = 30 位地址空间(地址位29:0)

这次,您没有任何用于索引 Level 0 表或 Level 1 表的其他位,因此配置的初始转换级别为Level 2 。

如上图所示,当虚拟地址空间的大小减小时,您需要更少级别的表来描述它。

这些例子是基于使用 4KB 的颗粒。同样的原理也适用于使用16KB和64KB的颗粒,但地址位发生了变化。

控制地址转换的寄存器

地址转换由以下系统寄存器的组合控制:

  • SCTLR_ELx

    M - 启用内存管理单元(MMU)

    C - 启用数据和统一缓存

    EE - 翻译表行走的字节顺序

  • TTBR0_ELx 和 TTBR1_ELx

    BADDR - 翻译表开始位置的物理地址(PA)(或中间物理地址,EL0/EL1)

    ASID - 用于非全局转换的地址空间标识符

  • TCR_ELx

    PS/IPS - PA或IPA空间的大小,最大输出地址大小

    TnSZ - 表中所覆盖的地址空间的大小

    TGn - 颗粒大小

    SH/IRGN/ORGN - MMU表行走所使用的可访问性和可共享性

    TBln - 禁用表行走到特定的表

  • MAIR_ELx

    Attr - 控制 Stage1 表中的类型和可缓存性。

MMU 禁用

当在翻译阶段禁用MMU时,所有地址都是平面映射的。平面映射表示输入地址和输出地址相同。

8、 翻译后备缓冲区(TLBs)的维护

翻译后备缓冲区(TLBs)缓存最近使用的翻译。这种缓存允许在后续查找中翻译被再次使用,而不需要重读表。

TLBs 是翻译的缓存,而不是翻译表的缓存。区别是微妙的。有几个寄存器字段控制如何解释翻译表条目。TLB 条目中包含的是根据表被遍历时的配置所给出的翻译表条目的解释。在Arm架构参考手册(Arm ARM)中,这样的寄存器字段被描述为 “允许在TLB中缓存”。

如果更改了转换表条目或影响条目解释方式的控件,则需要使TLB中受影响的条目无效。如果您不使这些条目无效,那么处理器可能会继续使用旧的翻译。

处理器不允许缓存到导致以下任何故障的TLB的转换:

  • 转换故障(未映射的地址)
  • 地址大小错误(地址超出范围)
  • 访问标志故障

因此,在第一次映射地址时,不需要发出TLB无效。但是,如果您想执行以下任何操作,则需要发出一个TLB无效:

  • 取消映射地址

    获取一个以前有效的地址或已映射的地址,并将其标记为错误地址。

  • 更改一个地址的映射

    更改输出地址或任何属性。例如,将地址从只读权限更改为读写权限。

  • 更改解释表的方式

    这种情况并不常见。但是,例如,如果颗粒大小改变了,那么对表的解释也会改变。因此,一个TLB无效将是必要的。

TLB操作的格式

TLBI 指令用于使 TLBs 中的条目无效。此指令的语法为:

TLBI < type >< level >{IS|OS} {, < xt >}

其中,

  • < type >,哪些条目无效

    All - 所有条目

    VA - 匹配在 Xt 的 VA 和 ASID 的条目 [ Entry matching VA and ASID in Xt ]

    VAA - 匹配在 Xt 中的 VA ,任何 ASID 的条目

    ASID - 匹配在 Xt 中的 ASID 的任何条目

    更多

  • < level >,要操作的地址空间

    E1 = EL0/1虚拟地址空间

    E2 = EL2虚拟地址空间

    E3 = EL3虚拟地址空间

  • < IS|OS >,无论一个操作是内部可共享(IS)还是外部可共享(OS)

    当 IS 添加到操作时,它将广播到内部共享域中的其他核心

    当 OS 添加到操作时,它将广播到外部共享域的其他核心(在Armv8.4-A中添加)

  • < Xt >,操作哪个地址或ASID

    仅用于按地址或ASID进行的操作

例如,考虑一个正在更新其内核转换表中的条目的操作系统(OS)。一个典型的 TLB 无效序列应该是这样的:

STR X1, [X5] 		// Write to translation table entry
DSB ISH 			// Barrier instructions - not covered in this guide
TLBI VAAE1IS , X0 	// Invalidate VA specified by X0, in EL0/1// virtual address space for all ASIDs
DSB ISH 			// Barrier instructions - not covered in this guide
ISB 				// Synchronize context on this processor

9、 地址翻译指令

地址转换(AT)指令允许软件查询特定地址的翻译。将翻译结果以及其属性写入到物理地址寄存器 PAR_EL1 中

AT指令的语法允许您指定要使用的翻译机制。例如,EL2可以查询EL0/EL1的翻译机制。但是,EL1不能使用AT指令来查询EL2的转换机制,因为这是对违反特权的。

如果所请求的翻译会导致错误,则不会生成异常。相反,将生成的故障类型将记录在 PAR_EL1 中。

10、 检查你的知识

Q:地址翻译的 stage 和 level 有什么区别?

A:Stage 是将输入地址转换为输出地址的过程。对于 Stage 1,这是从 VA 到 IPA 的过程,对于Stage 2,从 IPA 到 PA 的过程。Level 指的是给定翻译阶段的表。这也是如何将更大的块细分为更小的块。

Q:一个物理地址的最大大小是多少?

A:物理地址空间的最大大小是 IMPLEMENTATION DEFINED,最多52位(自Armv8.2-A)。

Q:哪个寄存器字段控制虚拟地址空间的大小?

A:TCR_ELx.TnSZ,或 VTCR_EL2.T0SZ 为 Stage 2。

Q:什么是翻译颗粒,支持的尺寸是多少?

A:它是可以描述的最小的内存块。支持的尺寸分别为4KB、16KB和64KB。

Q:TLBI 的 ALLE3 是做什么的?

A:它会使EL3虚拟地址空间中的所有TLB条目无效。

Q:导致翻译故障的翻译表项能否缓存在TLB中?

A:不,它不能存储在TLBs中。

Q:当禁用MMU时,地址将如何映射?

A:地址是平面映射的,因此输入地址和输出地址是相同的。

Q:什么是 ASID ?什么时候 TLB 条目包含一个 ASID ?

A:ASID 是一个地址空间标识符,它标识与翻译关联的应用程序。非全局映射(nG=1)在 TLBs 中用 ASID 进行标记。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/587526.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Android Gradle 插件】ProductFlavor 配置 ( ProductFlavor 引入 | ProductFlavor 参考文档地址 )

Android Plugin DSL Reference 参考文档 : 文档主页 : Android Plugin 2.3.0 DSL Reference android 模块配置文档 : AppExtension - Android Plugin 2.3.0 DSL Reference ProductFlavor 文档 : ProductFlavor - Android Plugin 2.3.0 DSL Reference 一、ProductFlavor 配置…

【数据结构】第2章线性表(头歌习题)【合集】

文章目录 第1关&#xff1a;实现顺序表各种基本运算的算法任务描述编程要求完整代码 第2关&#xff1a;实现单链表各种基本运算的算法任务描述编程要求完整代码 第3关&#xff1a;移除顺序表中所有值等于x的元素任务描述编程要求完整代码 第4关&#xff1a;逆置顺序表任务描述编…

【Kubernetes】kubectl 常用命令

kubectl 常用命令 1.基础命令2.部署命令3.集群管理命令4.故障诊断与调试命令5.高级命令6.设置命令7.其他命令 kubectl 是 Kubernetes 提供的命令行管理工具。通过使用 kubectl&#xff0c;可以管理和操作 Kubernetes。 1.基础命令 命令 说明 create通过文件名或标准输入创建 …

Java Object浅克隆深克隆

对象克隆 把A对象的属性值完全拷贝给B对象&#xff0c;也叫对象拷贝&#xff0c;对象复制。 实现Cloneable接口&#xff0c;表示当前类的对象就可以被克隆&#xff0c;反之&#xff0c;表示当前类的对象就不能克隆。 如果一个接口里面没有抽象方法&#xff0c;表示当前的接口…

LangChain(0.0.340)官方文档十一:Agents之Agent Types

LangChain官网、LangChain官方文档 、langchain Github、langchain API文档、llm-universe《Agent Types》、《Examples using AgentType》 文章目录 一、快速入门1.1 概念1.2 基本示例1.2.1 配置LangSmith1.2.2 使用LCEL语法创建Agents1.2.3 使用自定义runtime执行1.2.4 使用A…

CentOS 7 实战指南:文件操作命令详解

写在前面 想要快速掌握 CentOS 7 系统下的文件操作技巧吗&#xff1f;不用担心&#xff01;我为你准备了一篇详细的技术文章&#xff0c;涵盖了各种常用的文件操作命令。无论您是初学者还是有一定经验的用户&#xff0c;这篇文章都能帮助您加深对 CentOS 7 文件操作的理解&…

MySQL基础入门(二)

多表内容 一对多 这个内容是黑马的入门问题&#xff0c;可以带大家思考一下这个怎么设计 我们要知道一个岗位可以对应很多用户&#xff0c;而一个用户只能对应一个岗位&#xff0c;这就属于一对多的类型 那么我们需要怎么将他们进行关联呢&#xff1f; 现在我们可以通过一个…

【OpenAI Q* 超越人类的自主系统】DQN :Q-Learning + 深度神经网络

深度 Q 网络&#xff1a;用深度神经网络&#xff0c;来近似Q函数 DQN&#xff08;深度 Q 网络&#xff09; 深度神经网络 Q-LearningQ-Learning模型结构损失函数经验回放探索策略流程关联 DQN 优化DDQN&#xff1a;双 DQN&#xff0c;实现无偏估计Dueling DQN&#xff1a;提高…

Quartus的Signal Tap II的使用技巧

概述&#xff1a; Signal Tap II全称Signal Tap II Logic Analyzer&#xff0c;是第二代系统级调试工具&#xff0c;它集成在Quartus II软件中&#xff0c;可以捕获和显示实时信号&#xff0c;是一款功能强大、极具实用性的FPGA片上调试工具软件。 传统的FPGA板级调试是由外接…

ROS学习记录:用C++实现对wpr_simulation软件包中机器人的运动控制

一、在工作空间下输入catkin_make进行编译 二、在工作空间中输入source ./devel/setup.bash后回车 三、机器人的运动控制在wpr_simulation中有一个例子程序&#xff0c;在工作空间中输入&#xff1a; roslaunch wpr_simulation wpb_simple.launch后回车 四、就会启动一个仿真环…

菜鸟网络Java实习一面面经

自我介绍&#xff0c;做过的项目 巴拉巴拉 你项目中用到redis&#xff0c;可以介绍一下为什么使用它吗&#xff1f; 基于内存操作&#xff0c;内存读写速度快。 支持多种数据类型&#xff0c;包括String、Hash、List、Set、ZSet等。 支持持久化。Redis支持RDB和AOF两种持久…

Transformer基本结构

Transformer基本结构 输入部分、编码部分、解码部分、输出部分 1、输入部分 原文本嵌入层及其位置编码器目标文本嵌入层及其位置编码器 位置编码器(PositionalEncoding)&#xff1a;将词汇位置不同可能会产生不同语义的信息加入到词张量中&#xff0c;以弥补位置信息的缺失 …

Win10 + 4090显卡配置深度学习环境 + gaussian-splatting配置 + 实测自己的场景

目录 1 安装Anaconda 2023.09版本 2 安装CUDA11.8 3 安装深度学习库Cudnn8.6.0 4 安装VSCODE2019 5 安装Colmap3.8 6 安装git 7 安装Python3.10 Pytorch2.0.0 7 安装项目 8 采集数据 8.1 IPhone 14 pro 拍摄30张照片左右 做预处理 8.2 生成colmap位姿等信息 8.3 开…

STM32——F407定时器概述

1 定时器分类 定时器类型数量位号位宽时钟捕获/比较输出DMA请求计数互补输出基本2TIM6,TIM716bitAPB1-有递增-通用2TIM2,TIM532bitAPB14通道有递增、递减、中心对齐-通用2TIM3,TIM432bitAPB14通道有递增、递减、中心对齐-通用1TIM916bitAPB14通道有递增-通用2TIM10、TIM1116bi…

独立站的营销策略:吸引顾客的秘密武器

一、独立站的重要性 独立站是指企业自主建立的电子商务网站&#xff0c;具有独立的域名和运营管理权。通过独立站&#xff0c;企业可以展示产品信息、提供在线服务、进行促销活动等&#xff0c;与顾客建立互动和信任关系。独立站的重要性在于它可以帮助企业建立品牌认知度、提…

面向对象基础-类与对象-封装

1、类与对象 1.1 概念 类&#xff1a;类是一个抽象的概念&#xff0c;用于描述一类对象的特点。 对象&#xff1a;根据类的概念所创造的实体。 【思考】一个对象可以没有对应的类嘛&#xff1f; 不可以&#xff0c;因为必须现有类才能创建对象。 1.2 类的内容 类中最基础的内容…

pygame学习(一)——pygame库的导包、初始化、窗口的设置、打印文字

导语 pygame是一个跨平台Python库(pygame news)&#xff0c;专门用来开发游戏。pygame主要为开发、设计2D电子游戏而生&#xff0c;提供图像模块&#xff08;image&#xff09;、声音模块&#xff08;mixer&#xff09;、输入/输出&#xff08;鼠标、键盘、显示屏&#xff09;…

maven中dependencyManagement标签

简介 dependencyManagement正如其名&#xff0c;用于项目依赖的统一管理。 在父项目中的pom.xml文件中加入dependencyManagement标签即可完成依赖版本的声明。在声明完成后&#xff0c;子项目&#xff08;module&#xff09;中引用相同的依赖时可以不指定version标签自动引入…

【26.4K⭐】ShareX:一款开源免费、功能强大且丰富的截屏录屏软件

【26.4K⭐】ShareX&#xff1a;一款开源免费、功能强大且丰富的截屏录屏软件 在日常工作、学习和娱乐过程中&#xff0c;我们经常需要截取屏幕或者录制屏幕上特定区域中的内容并进行标记、编辑等操作。无论是为了记录重要的信息、分享有趣的内容&#xff0c;还是为了制作教程和…

toto的2023年终总结

第一次写年终总结&#xff0c;其实顺带是把大学四年的学习都给总结了一下&#xff0c;称之为大学总结更为合适吧&#xff1f; 其实把年终总结发在CSDN上有些不适&#xff0c;之前一直想着搭一个自己的博客也因为种种事情一直没有完成&#xff0c; 索性发在这里了&#xff0c;作…