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

学习体系结构 - 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 进行标记。

相关文章:

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

学习体系结构 - AArch64内存管理 Learn the architecture - AArch64 memory management Version 1.2 个人的英语很一般&#xff0c;对拿不准的翻译校准在后面添加了英文原文。 1、 概述 本指南介绍了AArch64中的内存转换&#xff0c;这是内存管理的关键。它解释了如何将虚拟地…...

Vue3 精通指南:如何在 setup 函数中巧妙利用 Vuex

在 Vue 3 中&#xff0c;如果你使用了组合式 API&#xff08;Composition API&#xff09;&#xff0c;你可以通过 setup 函数来设置组件的响应式状态和逻辑。要在 setup 函数中访问 Vuex 的 $store&#xff0c;你可以使用 useStore 钩子&#xff0c;它是 Vuex 4 为 Vue 3 提供…...

Linux 服务器安全策略技巧:启用账户锁定策略

Linux 服务器安全策略技巧:启用账户锁定策略 在Linux服务器上,启用账户锁定策略是一种重要的安全措施。通过锁定账户,可以防止未经授权的访问和恶意活动。本文将介绍如何在Linux服务器上启用账户锁定策略。 什么是账户锁定策略? 账户锁定策略是一种安全措施,用于限制对…...

野火霸道-V2+3.2寸屏+FreeRTOS+LVGL移植

摘要 基于野火霸道-V23.2寸屏的开发板&#xff0c;下载器为STLINK分为两个版本&#xff0c;FreeRTOS和裸机版本 裸机 裸机准备 lvgl v8.2版本的源码野火的《触摸画板-3.2寸》与《基本定时器》的代码例程 移植 将基本定时器代码移植到触摸画板-3.2寸的例程中&#xff0c;…...

操作教程|MeterSphere UI测试+VNC:简单、快捷地查看UI测试实时执行详情

编者注&#xff1a;本文为CSDN博主hxe116的原创文章。 原文链接为&#xff1a;https://blog.csdn.net/hxe116/article/details/134714960?spm1001.2014.3001.5502 作为一款一站式的开源持续测试平台&#xff0c;MeterSphere涵盖了测试跟踪、接口测试、UI测试和性能测试等功能…...

工具--Git详解

在当今的数字时代&#xff0c;版本控制系统已成为开发人员和团队之间协作的重要工具。其中&#xff0c;Git是最受欢迎的版本控制系统之一。它不仅在软件开发中广泛使用&#xff0c;还被应用于许多其他领域。在这篇博客中&#xff0c;我们将深入了解Git的工作原理、基本命令以及…...

windows server 2022 启用SYN攻击保护

2023.12.28 SYN攻击是什么&#xff1a; SYN攻击是黑客攻击的常用手段&#xff0c;也是最容易被利用的一种攻击手法&#xff0c;属于DDoS攻击的一种。它利用TCP协议缺陷&#xff0c;通过发送大量的半连接请求&#xff0c;耗费CPU和内存资源。 SYN攻击包括大量TCP连接的第一个包&…...

汽车保养软件app开发步骤

“增强您的动力&#xff0c;为您的旅程加油——每一刻都讲述着关爱的故事。构建汽车维护软件app&#xff0c;为您的车辆提供数字化的维修站&#xff0c;从而开启长寿之路。智能驾驶、互联驾驶、自信驾驶。” 疯狂地搜索旧收据并猜测上次换油时间的日子已经一去不复返了。如果您…...

【HarmonyOS】ArkTS语言介绍与组件方式运用

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…...

音频播放软件Foobar2000 mac特点介绍

Foobar2000 mac是一款高度可定制的音频播放器&#xff0c;适用于Windows平台。它支持各种音频格式&#xff0c;包括MP3、FLAC、AAC、WMA等&#xff0c;同时也支持各种音频插件和效果器&#xff0c;可以提供更好的音质和用户体验。 Foobar2000 mac软件特点 1. 高度可定制&#…...

Oracle动态性能视图 v$parameter 和 v$parameter2 的区别

v$parameter 的说明见这里&#xff1a; V$PARAMETER displays information about the initialization parameters that are currently in effect for the session. v$parameter2 的说明见这里&#xff1a; V$PARAMETER2 displays information about the initialization paramet…...

ssrf之dict协议和file协议

1.dict协议 dict是什么协议呢&#xff1f; 定义&#xff1a;词典网络协议&#xff0c;在RFC 2009中进行描述。它的目标是超越Webster protocol&#xff0c;并允许客户端在使 用过程中访问更多字典。Dict服务器和客户机使用TCP端口2628。 官方介绍&#xff1a;http://dict.o…...

OpenAI GPT 模型 API 接口新增参数 top_logprobs 和 logprobs

文章目录 一、前言二、主要内容三、总结 &#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 一、前言 在最新的 OpenAI 官方 APIs 文档中&#xff0c;Create chat completion 中新增了 top_logprobs 和 logprobs 这两个关键参数。 官方文档地址&#xff…...

React项目打包流程

一、React项目打包流程 一、React项目打包流程1. 项目打包打包命令&#xff1a;npm run build2. 预览接着命令行会提示执行&#xff1a; 先&#xff1a;npm install -g serve 然后执行此命令&#xff1a;serve -s build二、打包优化 - 配置路由懒加载 二、打包优化 - 配置路…...

04-获取认证的用户身份信息

存储用户信息的方式 获取用户信息的流程 用户提交账号和密码后,DaoAuthenticationProvider调用UserDetailsService接口实现类的loadUserByUsername()方法,该方法可以接收请求参数username的值,然后根据该值查询用户信息,最后将账号,密码,权限封装到UserDetails对象中并返回给…...

二叉树的中序遍历,力扣

目录 题目地址&#xff1a; 题目&#xff1a; 解题方法&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 代码实现&#xff1a; 注&#xff1a; 代码实现&#xff08;递归&#xff09;&#xff1a; 代码实现&#xff08;迭代&#xff09;&#xff1a; 题目地址&#xf…...

shiro1.10版本后-IniSecurityManagerFactory过期失效

1、问题概述&#xff1f; 今天在研究了shiro的新版本shiro1.13.0版本&#xff0c;发现用了很长时间的IniSecurityManagerFactory工厂失效了。 从下图中可以看出&#xff0c;在新版本中IniSecurityManagerFactory被打上了过期线了。 那么问题来了&#xff0c;新版本如何使用呢…...

阿里后端实习二面

阿里后端实习二面 记录面试题目&#xff0c;希望可以帮助到大家 类加载的流程&#xff1f; 类加载分为三个部分&#xff1a;加载、连接、初始化 加载 类的加载主要的职责为将.class文件的二进制字节流读入内存(JDK1.7及之前为JVM内存&#xff0c;JDK1.8及之后为本地内存)&…...

「Kafka」生产者篇

「Kafka」生产者篇 生产者发送消息流程 在消息发送的过程中&#xff0c;涉及到了 两个线程 ——main 线程和Sender 线程。 在 main 线程中创建了 一个 双端队列 RecordAccumulator。 main线程将消息发送给RecordAccumulator&#xff0c;Sender线程不断从 RecordAccumulator…...

C语言实现RSA算法加解密

使用c语言实现了RSA加解密算法&#xff0c;可以加解密文件和字符串。 rsa算法原理 选择两个大素数p和q&#xff1b;计算n p * q;计算φ(n)(p-1)(q-1)&#xff1b;选择与φ(n)互素的整数d&#xff1b;由de1 mod φ(n)计算得到e&#xff1b;公钥是(e, n), 私钥是(d, n);假设明…...

如何设计前后端分离的系统架构?

如何将前端页面和后端Java代码进行集成&#xff1f; 将前端页面和后端Java代码进行集成通常需要使用一些特定的工具和技术。以下是一些常见的方法&#xff1a; 使用RESTful API&#xff1a;REST&#xff08;Representational State Transfer&#xff09;是一种基于HTTP协议构…...

【强化学习】SARAS代码实现

前言 SARAS&#xff0c;假设环境状态和动作状态都是离散的。利用动作价值矩阵来进行行为的预测。其主要就是利用时序差分的思想&#xff0c;对动作价值矩阵进行更新。 代码实现 import gymnasium as gym import numpy as npclass sarsa():def __init__(self, states_n, acti…...

P1019 [NOIP2000 提高组] 单词接龙 刷题笔记

P1019 [NOIP2000 提高组] 单词接龙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路来自 大佬 Chardo 的个人中心 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 匹配 &#xff1a; 将 第一个字符串末尾 和第二个字符串第一个开始匹配 如果 j<i这段走完了 flag还没…...

如何实现WinApp的UI自动化测试?

WinApp&#xff08;WindowsAPP&#xff09;是运行在Windows操作系统上的应用程序&#xff0c;通常会提供一个可视的界面&#xff0c;用于和用户交互。例如运行在Windows系统上的Microsoft Office、PyCharm、Visual Studio Code、Chrome&#xff0c;都属于WinApp。常见的WinApp&…...

chrome扩展程序开发之在目标页面运行自己的JS

原文地址&#xff1a;https://qdgithub.com/home/index/article/aid/247.html chrome 插件开发的入门介绍&#xff0c;实现利用 chrome 扩展实现在目标网页运行我们的 js 的功能。关于 chrome 扩展的详细内容&#xff0c;可以通过官网了解。 开发工具很简单&#xff0c;记事本…...

NLP项目之语种识别

目录 1. 代码及解读2. 知识点n-grams仅保留最常见的1000个n-grams。意思是n1000 ? 1. 代码及解读 in_f open(data.csv) lines in_f.readlines() in_f.close() dataset [(line.strip()[:-3], line.strip()[-2:]) for line in lines] print(dataset[:5])[(1 december wereld…...

Linux lpr命令教程:如何使用lpr命令打印文件(附案例详解和注意事项)

Linux lpr命令介绍 lpr命令在Unix-like操作系统中用于提交打印任务。如果在命令行中指定了文件名&#xff0c;那么这些文件将被发送到指定的打印机&#xff08;如果没有指定目的地&#xff0c;则发送到默认目的地&#xff09;。如果命令行中没有列出文件&#xff0c;lpr将从标…...

浅谈C语言inline关键字

对于C开发者来说&#xff0c;inline是个再熟悉不过的关键字&#xff0c;因为默认的成员函数都是inline&#xff0c;也是常规高校教材中宣扬C的“优势”之一。 但是C语言其实也是支持inline关键字的&#xff0c;而且是很早期的gcc就支持了该关键字。在Linux0.12版本内核代码中也…...

Flink1.17实战教程(第六篇:容错机制)

系列文章目录 Flink1.17实战教程&#xff08;第一篇&#xff1a;概念、部署、架构&#xff09; Flink1.17实战教程&#xff08;第二篇&#xff1a;DataStream API&#xff09; Flink1.17实战教程&#xff08;第三篇&#xff1a;时间和窗口&#xff09; Flink1.17实战教程&…...

OpenCV实战 -- 维生素药片的检测记数

文章目录 检测记数原图经过操作开始进行消除粘连性--形态学变换总结实现方法1. 读取图片&#xff1a;2. 形态学处理&#xff1a;3. 二值化&#xff1a;4. 提取轮廓&#xff1a;5. 轮廓筛选和计数&#xff1a; 分水岭算法&#xff1a;逐行解释在基于距离变换的分水岭算法中&…...

【AI】注意力机制与深度学习模型

目录 一、注意力机制 二、了解发展历程 2.1 早期萌芽&#xff1a; 2.2 真正意义的注意力机制&#xff1a; 2.3 2015 年及以后&#xff1a; 2.4 自注意力与 Transformer&#xff1a; 2.5 BERT 与预训练模型&#xff1a; 三、基本框架 1. 打分函数&#xff08;Score Fun…...

HTML5和JS实现新年礼花效果

HTML5和JS实现新年礼花效果 2023兔年再见&#xff0c;2024龙年来临了&#xff01; 祝愿读者朋友们在2024年里&#xff0c;身体健康&#xff0c;心灵愉悦&#xff0c;梦想成真。 下面是用HTML5和JS实现新年礼花效果&#xff1a; 源码如下&#xff1a; <!DOCTYPE html>…...

【owt-server】一些构建项目梳理

【owt-server】清理日志&#xff1a;owt、srs、ffmpeg 【owt】p2p client mfc 工程梳理【m98】webrtc vs2017构建带符号的debug库【OWT】梳理构建的webrtc和owt mfc工程 m79的mfc客户端及owt-client...

Linux shell编程学习笔记38:history命令

目录 0 前言 1 history命令的功能、格式和退出状态1.1 history命令的功能1.2 history命令的格式1.3退出状态2 命令应用实例2.1 history&#xff1a;显示命令历史列表2.2 history -a&#xff1a;将当前会话的命令行历史追加到历史文件~/.bash_history中2.3 history -c&#xf…...

elasticsearch安装教程(超详细)

1.1 创建网络&#xff08;单点部署&#xff09; 因为我们还需要部署 kibana 容器&#xff0c;因此需要让 es 和 kibana 容器互联&#xff0c;所有先创建一个网络&#xff1a; docker network create es-net 1.2.加载镜像 采用的版本为 7.12.1 的 elasticsearch&#xff1b;…...

arkts中@Watch监听的使用

概述 Watch用于监听状态变量的变化&#xff0c;当状态变量变化时&#xff0c;Watch的回调方法将被调用。Watch在ArkUI框架内部判断数值有无更新使用的是严格相等&#xff08;&#xff09;&#xff0c;遵循严格相等规范。当在严格相等为false的情况下&#xff0c;就会触发Watch的…...

【Jmeter】Jmeter基础9-BeanShell介绍

3、BeanShell BeanShell是一种完全符合Java语法规范的脚本语言,并且又拥有自己的一些语法和方法。 3.1、Jmeter中使用的BeanShell 在Jmeter中&#xff0c;除了配置元件&#xff0c;其他类型的元件中都有BeanShell。BeanShell 是一种完全符合Java语法规范的脚本语言,并且又拥…...

详解数组的轮转

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary-walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…...

html 表格 笔记

<!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>第二个页面</title><meta name"language" content"cn"> </head> <body><h2 sytle"width:500px;…...

计算机网络【HTTP 面试题】

HTTP的请求报文结构和响应报文结构 HTTP请求报文主要由请求行、请求头、空行、请求正文&#xff08;Get请求没有请求正文&#xff09;4部分组成。 1、请求行 由三部分组成&#xff0c;分别为&#xff1a;请求方法、URL以及协议版本&#xff0c;之间由空格分隔&#xff1b;请…...

linux基于用户身份对资源访问进行控制的解析及过程

linux中用户分为三类 1.超级用户&#xff08;root&#xff09; 拥有至高无上的权限 2.普通用户 人为创建、权限小&#xff0c;权限受到控制 3.程序用户 运行程序的用户&#xff0c;不是给人使用的&#xff0c;给程序使用的&#xff0c;一般不给登录&#xff01; 组账…...

手动创建idea SpringBoot 项目

步骤一&#xff1a; 步骤二&#xff1a; 选择Spring initializer -> Project SDK 选择自己的JDK版本 ->Next 步骤三&#xff1a; Maven POM ->Next 步骤四&#xff1a; 根据JDK版本选择Spring Boot版本 11版本及以上JDK建议选用3.2版本&#xff0c;JDK为11版本…...

【Go语言入门:Go语言的数据结构】

文章目录 3.Go语言的数据结构&#xff1a;3.1. 指针3.2. struct&#xff08;结构体&#xff09;3.3. Map(映射,哈希&#xff09; 3.Go语言的数据结构&#xff1a; 简介&#xff1a; 在Go语言中&#xff0c;数据结构体可以分为四种类型&#xff1a;基础类型、聚合类型、引用类型…...

QT designer的ui文件转py文件之后,实现pycharm中运行以方便修改逻辑,即添加实时模板框架

为PyCharm中的实时模板&#xff0c;你需要遵循以下步骤&#xff1a; 打开PyCharm的设置: 选择 File > Settings&#xff08;在macOS上是 PyCharm > Preferences&#xff09;。 导航到实时模板: 在设置中找到 Editor > Live Templates。 添加新的模板组 (可选): 为了…...

什么是负载均衡?

负载均衡是指在计算机网络领域中&#xff0c;将客户端请求分配到多台服务器上以实现带宽资源共享、优化资源利用率和提高系统性能的技术。负载均衡可以帮助小云有效解决单个服务器容量不足或性能瓶颈的问题&#xff0c;小云通过平衡流量负载&#xff0c;使得多台服务器能够共同…...

Python和Java的优缺点

Python的优点&#xff1a; 简单易学&#xff1a;Python的语法简洁清晰&#xff0c;易于学习和理解。丰富的库和框架&#xff1a;Python拥有庞大的标准库和活跃的开源社区&#xff0c;可以快速使用各种功能强大的库和框架&#xff0c;比如NumPy、Pandas、Django等。可读性强&am…...

AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密)

文章目录 AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密)概述增加2个封装函数的AES库aes.haes.c在官方测试程序上改的测试程序(用来测试这2个封装函数)END AES - 在tiny-AES-c基础上封装了2个应用函数(加密/解密) 概述 在github山有个星数很高的AES的C库 tiny-AES-c …...

51和32单片机读取FSR薄膜压力传感器压力变化

文章目录 简介线性电压转换模块51单片机读取DO接线方式51代码实验效果 32单片机读取AO接线方式32代码实验效果 总结 简介 FSR薄膜压力传感器是可以将压力变化转换为电阻变化的一种传感器&#xff0c;单片机可以读取然后作为粗略测量压力&#xff08;仅提供压力变化&#xff0c;…...

【maven】pom.xml 文件详解

有关 maven 其他配置讲解参考 maven 配置文件 setting.xml 详解 pom.xml 文件是 Maven 项目的核心配置文件&#xff0c;其中包含了项目的元数据、构建配置、依赖管理等信息。以下是一个 pom.xml 文件的主要部分&#xff1a; <?xml version"1.0" encoding"U…...

SpringMVC源码解析——DispatcherServlet初始化

在Spring中&#xff0c;ContextLoaderListener只是辅助功能&#xff0c;用于创建WebApplicationContext类型的实例&#xff0c;而真正的逻辑实现其实是在DispatcherServlet中进行的&#xff0c;DispatcherServlet是实现Servlet接口的实现类。Servlet是一个JAVA编写的程序&#…...