学习体系结构 - 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.mfbz.cn/a/281577.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

常用设计模式全面总结版(JavaKotlin)

这篇文章主要是针对之前博客的下列文章的总结版本: 《设计模式系列学习笔记》《Kotlin核心编程》笔记:设计模式【Android知识笔记】FrameWork中的设计模式主要为了在学习了 Kotlin 之后,将 Java 的设计模式实现与 Kotin 的实现放在一起做一个对比。 一、创建型模式 单例模…

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

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

【LeetCode每日一题】1154. 一年中的第几天(直接计算+调用库函数)

2023-12-31 文章目录 [1154. 一年中的第几天](https://leetcode.cn/problems/day-of-the-year/)方法一&#xff1a;直接计算思路&#xff1a; 方法二&#xff1a;调用库函数思路 1154. 一年中的第几天 方法一&#xff1a;直接计算 思路&#xff1a; 1.根据所给的字符串&#…

第二节 linux操作系统安装与配置

一&#xff1a;Vmware虚拟机安装与使用   ①VMware是一个虚拟PC的软件&#xff0c;可以在现有的操作系统上虚拟出一个新的硬件环境&#xff0c;相当于模拟出一台新的PC &#xff0c;以此来实现在一台机器上真正同时运行多个独立的操作系统。   ②VMware主要特点&#xff1a…

[LitCTF 2023]Vim yyds

[LitCTF 2023]Vim yyds wp 题目页面如下&#xff1a; 搜索一番&#xff0c;没有发现任何信息。题目描述中说到了源码泄露&#xff0c;那么先进行目录扫描。 dirsearch 目录扫描 命令&#xff1a; dirsearch -u "http://node4.anna.nssctf.cn:28588/"返回结果&…

PTA——计算火车运行时间

本题要求根据火车的出发时间和达到时间&#xff0c;编写程序计算整个旅途所用的时间。 输入格式&#xff1a; 输入在一行中给出2个4位正整数&#xff0c;其间以空格分隔&#xff0c;分别表示火车的出发时间和到达时间。每个时间的格式为2位小时数&#xff08;00-23&#xff0…

最简单的基于 SDL2 的音频播放器

最简单的基于 SDL2 的音频播放器 最简单的基于 SDL2 的音频播放器正文工程文件下载 参考雷霄骅博士的文章&#xff0c;链接&#xff1a;最简单的基于FFMPEGSDL的音频播放器&#xff1a;拆分-解码器和播放器 最简单的基于 SDL2 的音频播放器 正文 SDL2 音频播放器实现了播放 …

抖音详情API:开发环境搭建与工具选择

随着短视频的流行&#xff0c;抖音已经成为了一个备受欢迎的社交媒体平台。对于开发人员而言&#xff0c;利用抖音详情API开发定制化的抖音应用具有巨大的潜力。本文将为你详细介绍开发抖音应用的开发环境搭建与工具选择&#xff0c;帮助你顺利地开始开发工作。 一、开发环境搭…

Github项目推荐-vocal-separate

项目地址 vocal-separate: 项目简述 这是一个音乐和人声分离的项目&#xff0c;基于python开发。有图形化操作界面&#xff0c;看起来还不错。 项目截图

Centos7安装Docker和Docker-Compose

环境 操作系统&#xff1a;Centos 7.9 root环境 Docker安装 卸载原先的Docker环境 如果你先前的操作系统安装了Docker环境&#xff0c;请卸载 Docker 相关的软件包&#xff0c;没有则忽略这一步。 yum remove docker \docker-client \docker-client-latest \docker-common \doc…

计数排序 CountingSort

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序&#xff0c;计数排序要求输入的数据必须是有确定范围的整数。 动画演示 : 案例代码 : (此代码有些瑕疵 , 不能处理负数) public static void main(String[] args) {//int[…

【Web API系列】使用异步剪贴板API(async clipboard)的图像的编程复制和粘贴

文章目录 前言一、将数据写入剪切板1. WriteText()2. Write()3. 监听复制事件 二、从剪切板读取数据1.readText()2.read()3. 处理粘贴的文件4. 监听读剪切板事件 三、申请权限政策集成 四、功能检测五、处理多个 MIME 类型 前言 访问系统剪贴板的传统方法是通过 document.exec…

WAZUH的安装、设置代理

wazuh安装 wazu的安装分为以下两种方式 官方文档&#xff1a;https://wazuh.com/blog/detecting-common-linux-persistence-techniques-with-wazuh/ 1、自定义安装 这种方式就是一步一步的安装 直接参考官方文档&#xff1a; 这里就不详细介绍了&#xff0c;本次主要介绍的…

vue3全网最全教程-----(4)

目录 6. 组件通信 6.1. 【props】 6.2. 【自定义事件】 6.3. 【mitt】 6.4.【v-model】 6.5.【$attrs 】 6.6. 【refs、parent】 6.7. 【provide、inject】 6.8. 【pinia】 6.9. 【slot】 1. 默认插槽 2. 具名插槽 3. 作用域插槽 7. 其它 API 7.1.【shallowRef 与…

Obsidian笔记软件无公网远程同步数据到群辉Webdav

文章目录 1. 群晖开启Webdav服务2. 群晖安装Cpolar3. 配置Webdav远程地址4. Obsidian 安装Remotely Save5. Obsidian远程连接Webdav6. 固定Cpolar公网地址7. PC和移动端笔记同步演示 Obsidian是一款笔记软件&#xff0c;它基于Markdown&#xff0c;支持Windows、macOS、iOS和An…

程序员绩效考核表就是这么简单

大家好&#xff0c;今天给大伙分享一份程序员的绩效考核表&#xff0c;仅供参考&#xff01; 《程序员绩效考核表》

EasyExcel详解(结合官方文档)

EasyExcel 零、前言 文章是根据官方文档&#xff0c;加上自己的测试运行总结出来的&#xff0c;目前只总结的EasyExcel读的部分&#xff0c;写的部分还未完结&#xff0c;后续会更新1、官方文档 https://easyexcel.opensource.alibaba.com/2、EasyExcel的maven依赖 <!--…

Git 常用命令知识笔记

Git 仓库数据结构 Git 仓库由一个个的 commit 组成某些 commit 上会有一些 branch 指向它们&#xff0c;这些 branch 的本质是引用有一个特殊的引用叫做 HEAD&#xff0c;它始终指向当前的位置&#xff0c;这个位置可以是 commit&#xff0c;也可以是 branch staging area 暂存…

Linux:进程退出 与 进程等待wait,waitpid

1.进程退出 1.1 进程退出介绍 进程退出场景 代码运行完毕&#xff0c;结果正确代码运行完毕&#xff0c;结果不正确代码异常终止 进程常见退出方法&#xff1a; 1. 正常终止&#xff08;可以通过 echo $? 查看进程退出码&#xff09;&#xff1a; 从main return调用exit…

为什么广西建筑模板在行业中备受推崇?

广西建筑模板以其卓越的品质和性能&#xff0c;在建筑行业中享有极高的声誉。在众多优秀生产商中&#xff0c;能强优品木业作为广西建筑模板的四大品牌之一&#xff0c;以25年的专业生产经验&#xff0c;成为业界的佼佼者。 高质量原材料 广西的气候和土壤条件非常适合木材生…