【ARM Cortex-M3指南】3:Cortex-M3基础

文章目录

  • 三、Cortex-M3基础
    • 3.1 寄存器
      • 3.1.1 通用目的寄存器 R0~R7
      • 3.1.2 通用目的寄存器 R8~R12
      • 3.1.3 栈指针 R13
      • 3.1.4 链接寄存器 R14
      • 3.1.5 程序计数器 R15
    • 3.2 特殊寄存器
      • 3.2.1 程序状态寄存器
      • 3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器
      • 3.2.3 控制寄存器
    • 3.3 操作模式
    • 3.4 异常和中断
    • 3.5 向量表
    • 3.6 栈存储操作
      • 3.6.1 栈的基本操作
      • 3.6.2 Cortex-M3 栈的应用
      • 3.6.3 Cortex-M3 的双栈模型
    • 3.7 复位流程

三、Cortex-M3基础

3.1 寄存器

前面已经介绍过了,Cortex-M3处理器具有寄存器R0~R15以及多个特殊寄存器。 R0R12为通用目的寄存器,不过有些16位Thumb指令只能访问R0R7(低寄存器),而 32位Thumb-2指令则可以访问所有的寄存器,特殊寄存器具有预定义的功能,并且只能通过特殊寄存器访问指令操作。

3.1.1 通用目的寄存器 R0~R7

通用目的寄存器R0~R7也称作低寄存器,它们可以通过所有的16位Thumb指令和 32位Thumb-2指令访问。这些寄存器都是32位宽的,并且复位值为不可预测的。

3.1.2 通用目的寄存器 R8~R12

寄存器R8~R12也称作高寄存器,它们可以通过所有的Thumb-2指令访问,而有些 16位的Thumb指令则不可以。这些寄存器都是32位宽,并且复位值是不可预测的。

3.1.3 栈指针 R13

R13为栈指针(SP),Cortex-M3中存在两个SP,利用这种结构,我们可以设置两个独立的栈指针。在使用寄存器名为R13时,只能访问当前的SP,要访问另一个的话,只能通过特殊指令

  1. 从通用目的寄存器到特殊寄存器 - MSR
  2. 从特殊寄存器到通用目的寄存器 - MRS

这两个栈指针为:

  1. 主栈指针(MSP):在ARM文献中也叫SP_main,这是默认的SP,用于操作系统内核、异常处理和所有需要特权访问的应用程序代码。
  2. 进程栈指针(PSP):在ARM文献中也叫SP_process,用于基本的应用程序代码(未运行异常处理时)。

image.png

image.png

使用两个SP是没有必要的,简单的应用程序可以完全依赖MSP。SP用于像PUSH和POP之类的栈存储处理。

对于Cortex-M3,访问栈空间的指令为PUSH和POP,汇编语法如下(每个分号[;]之后的文字为注释)。

PUSH {R0}
步骤1:R13 = R13 - 4
步骤2:存储器[R13] = R0

POP {R0}
步骤1:R0 = 存储器[R13]
步骤2:R13 = R13 + 4

Cortex-M3使用满递减的栈处理(本章的“栈存储操作”中有对这方面的详细介绍),因此,当新的数据存入栈后,SP减小。PUSH和POP通常用于在子例程开始时将寄存器内容保存至栈空间,之后会在子例程结束后将寄存器内容从栈中恢复。PUSH和POP可以在一条指令中操作多个寄存器:

subroutine_1
PUSH {R0 - R7, R12, R14}
...
POP {R0 - R7, R12, R14}
BX R14

在程序代码中,可以使用SP(栈指针)代替R13。这就意味着,在程序代码内部,MSP和PSP都可以被称作R13/SP。不过,你可以使用特殊寄存器访问指令(MRS/MSR)来操作特定的SP。

由于寄存器的PUSH和POP操作总是字对齐(0x4,0x8),故SP的第0位和第1位被硬连接为0,并且读出总是0。

image.png

3.1.4 链接寄存器 R14

R14为链接寄存器(LR),在汇编程序中,可以写作R14或LR。LR用于子例程或函数调用时保存返回地址,例如,在使用跳转链接(BL)指令时:
image.png

尽管PC的第0位总是为0(由于指令都是字对齐或者半字对齐的),LR的第0位是可读可写的。这是因为在Thumb指令集中,第0位通常用于指明ARM/Thumb状态,要将 Cortex-M3上实现的Thumb-2程序运行在其他支持Thumb-2技术的ARM处理器上,这个最低位(LSB)需要为可读可写的。

3.1.5 程序计数器 R15

R15就是PC,在汇编代码中可以使用R15或PC进行访问。由于Cortex-M3处理器的流水线特性,在读这个寄存器时,你会发现读出值和正在执行的指令位置不同,通常差4,例如:

image.png

对PC的写操作会引起跳转(但LR不会更新),由于指令地址必须是半字对齐的,PC读出值的LSB(最低位)总是0。不过,对于跳转,不管是通过写PC还是使用跳转指令,目标地址的LSB都应该置1,以指明当前处于Thumb状态;如果为0的话,处理器会试图切换至ARM状态,而Cortex-M3的这一操作会导致错误异常。

3.2 特殊寄存器

Cortex-M3处理器具有多个特殊寄存器:

  • 程序状态寄存器(PSR);
  • 中断屏蔽寄存器(PRIMASK、FAULTMASK、BASEPRI);
  • 控制寄存器(CONTROL)。

特殊寄存器只能通过指令MSRMRS访问,它们没有存储器地址:

  • MSR <special_reg> <reg>:写入特殊寄存器。
  • MRS <reg> <special_reg>:读取特殊寄存器。

3.2.1 程序状态寄存器

PSR分为三个状态寄存器:

  1. 应用程序状态寄存器 - APSR
  2. 中断程序状态寄存器 - IPSR(只读)
  3. 执行程序状态寄存器 - EPSR(只读)

这三个PSR可以通过特殊寄存器访问指令MSRMRS进行整体操作或者分开操作,整体操作时使用寄存器名xPSR

image.png

image.png

image.png

如果将这个寄存器同ARM7的当前程序状态寄存器(CPSR)相比,可能会发现ARM7中用的某些位域已经不存在了。由于Cortex-M3不具有ARM7定义的操作模式,模式(M)位就去掉了;Tumb(T)位变为了第24位;中断状态(I和F)位则被新的中断寄存器(PRIMASK)代替,这些寄存器同PSR是相互独立的。为了便于比较,传统ARM处理器的 CPSR寄存器如图3.5所示。

image.png

3.2.2 PRIMASK、FAULTMASK和BASEPRI寄存器

PRIMASK、FAULTMASK和BASEPRI寄存器用于禁止异常。

寄存器名描述
PRIMASK寄存器中仅有1位,在其置位时,允许不可屏蔽中断和硬件错误异常,其他所有中断和异常都会被屏蔽;默认为0,不屏蔽中断。
FAULTMASK寄存器中仅有1位,在其置位时,允许不可屏蔽中断NMI,其他所有中断和硬件错误处理异常都会被屏蔽;默认为0,不屏蔽中断。
BASEPRI寄存器中最多8位(取决于优先级的实际位宽),定义了屏蔽优先级。在其置位时,相同或者更低等级的所有中断都被禁止,更高优先级的中断仍可执行。如果设置为0,则屏蔽功能禁止(默认)。

在时间敏感的任务中需要暂时禁止中断时,可以使用PRIMASK和BASEPRI寄存器。当一个任务崩溃时,OS可以使用FAULTMASK暂时禁止错误处理。在这种情况下,任务崩溃时可能会产生多个不同错误。内核开始清理操作时,它也许不想被崩溃进程引起的其他错误打断,因此,利用FAULTMASK,OS内核就获得了处理错误状态的时间。

image.png

image.png
image.png

3.2.3 控制寄存器

控制寄存器用于定义特权等级和SP的选择,该寄存器为2位宽。

image.png

  1. CONTROL[1]

对于Cortex-M3,CONTROL[1]位在处理模式时总是0(使用MSP),不过在线程或者基本等级中,它可以是0或者1。

该位只有在内核处于特权线程下才可写,在其他模式下,该位是不允许进行写操作的。除了写这个寄存器外,也可以在异常返回时修改LR的第2位来修改这一位。

  1. CONTROL[0]

CONTROL[0]位只有在特权等级下可写,一旦进入用户等级,要想切换回特权状态,只能触发一次中断并且在异常处理中进行修改。

image.png

3.3 操作模式

当处理器运行在线程模式中时,它可以处在特权或用户等级,不过处理模式只能位于特权等级。当处理器退出复位时,它处于线程模式并且具有特权访问权限。

在用户访问等级(线程模式),对系统控制空间(SCS,存储器空间的一部分,用于配置寄存器和调试部件)的访问是不允许的。另外,访问特殊寄存器的指令(如MSR,访问APSR时除外)也不可以使用。如果用户访问等级的程序要访问SCS或特殊寄存器,错误异常就会产生。

处在特权访问等级的软件可以通过控制寄存器将程序切换至用户访问等级。异常发生时,处理器总会切换至特权状态,并且在退出异常处理时返回到之前的状态。用户程序无法直接通过写控制寄存器切回特权状态,在返回线程模式时,它必须通过设置控制寄存器的异常处理才可以切换至特权访问等级(见图3.7)。

image.png

对特权和用户访问等级的支持提供了一个更加安全和健壮的架构,例如,当用户程序错误时,它不会破坏嵌套向量中断控制器(NVIC)中的控制寄存器。另外,如果存储器保护单元(MPU)存在的话,用户程序对特权进程使用的存储器区域的访问可能会被禁止。

在简单的应用中,无须区分特权和用户访问等级。在这种情况下,也无须使用用户访问等级以及设置控制寄存器。

你可以将用户应用程序的栈同内核栈相分离,这样可以避免用户程序栈的错误操作引起的系统崩溃。根据这种设计,用户程序(运行在线程模式)使用PSP,而异常处理则使用 MSP。SP在进入或离开异常处理时自动切换(见3.6.3节),第8章有这个方面的详细介绍。

控制寄存器定义了处理器的模式和访问等级,当控制寄存器的第0位为0时,异常发生会引起处理器模式的改变(见图3.8和图3.9)。

image.png

当控制寄存器的第0位为1时(运行用户应用程序的线程),异常发生会引起处理器模式和访问等级的改变(见图3.10)。

只有在特权等级中,控制寄存器的第0位才是可编程的(见图2.5)。用户等级的程序要想切换至特权状态,它必须发起一个中断(例如,请求管理调用[SVC])并在中断处理中修改CONTROL[0]。

3.4 异常和中断

Cortex-M3支持多个异常,其中包括固定数量的系统异常和通常被称作IRQ的多个中断。根据个体设计的不同,Cortex-M3微控制器中断输人的数量也有所不同。外设产生的中断,除了系统节拍定时器,也被连接至中断输入信号上。中断输入的数量一般为16或 32,不过,有些微控制器的中断输入可能会更多(或更少)。

除了中断输入之外,处理器还有一个不可屏械中断(NMI)输入信号,NMI的实际使用情况取决于微控制器或片上系统(SoC)的设计。多数情况下,NMI可以连接至看门狗时钟,或者电压监控模块,这样在电压降到一定程度时处理器会收到警告。NMI异常随时可以激活,甚至是在内核刚刚退出复位后。

Cortex-M3支持的异常如表3.4所示。其中多个系统异常为错误处理异常,它们可由许多错误条件触发。NVIC也提供了多个错误状态寄存器,这样异常处理可以根据这些寄存器确定异常的原因。

如果要了解Cortex-M.3异常处理的细节,可以参考第7~9章的内容。

image.png

3.5 向量表

当Cortex-M3的异常发生并被处理器接受时,对应的异常处理就会执行。为了确定异常处理的起始地址,处理器使用了一种向量表机制。向量表是系统存储器中的字数据数组,每个元素代表了一种异常类型的起始地址。向量表的位置是可以重置的,该位置由NVIC中的重定位寄存器决定(见表3.5)。复位后,该重定位寄存器被置为0,因此,向量表在复位后位于地址0x0处。

image.png

例如,若复位的异常类型为1,那么复位向量的地址为1×4(每个字为4字节),也就是 0x00000004,NM1向量(类型2)位于2×4=0x00000008位置。地址0x00000000用于存放 MSP的初始值。

每个异常类型的LSB表示异常是否允许在Thumb状态中执行,由于Cortex-M3只支持Thumb指令,所有的异常向量的LSB都应该置1。

3.6 栈存储操作

对于Cortex-M3,栈的PUSH和POP除了可以被普通软件控制外,还可在进入或退出异常/中断处理时自动执行。本节中,我们来看一下软件栈操作(异常处理期间的栈操作在第9章中介绍)。

3.6.1 栈的基本操作

般来说,栈操作也就是存储器的写或读操作,只是地址被指定为SP。寄存器中的数据由PUSH操作存人栈存储中,而且稍后可以由POP操作恢复到寄存器中。在PUSH和 POP期间,SP的内容自动调整,因此,多次PUSH不会清除之前的压栈数据。

栈的功能为将寄存器内容存到存储器中,以便处理任务结束后它们还可以被恢复。例如,对于每次存储(PUSH),都必须有对应的读(POP),而且POP操作的地址应该同PUSH操作的地址相匹配。使用PUSH/POP指令时,SP自动增加/减小。

当程序控制返回到主程序时,R0~R2的内容同之前的一致,应该注意PUSH和POP的顺序:POP应是PUSH的反顺序。

由于PUSH和POP指令允许多次存储和加载,因此这些操作可以简化。在这种情况下,处理器会将寄存器POP的顺序自动反过来(见图3.12)。

image.png

RETURN可以同POP操作合并在一起,要实现这个目的,可以将LR存入栈中,并且在子例程结束时将其送回PC(见图3.13)。

image.png

3.6.2 Cortex-M3 栈的应用

Cortex-M3使用了一种满递减的栈操作模型,SP指向压入栈存储的最后一个数据,SP在新的PUSH操作前减小。图3.14为指令PUSH{R0}执行的例子。

image.png

对于POP操作,数据被从SP指向的位置中读出,然后SP增加。存储器位置的数据不会变化,但下次PUSH操作发生时则会被覆盖(见图3.15)。

由于每次PUSH/POP操作传输4字节的数据(每个寄存器包含1个字,也就是4字节),SP每次会增加/减小4字节,如果多于1个寄存器需要压栈或出栈则是4的倍数。

在Cortex-M3中,R13被定义为SP。当中断发生时,多个寄存器会自动压栈,在这个过程中,R13会被用作SP。类似地,在退出中断处理时,压栈的寄存器会自动地恢复/出栈,SP的值也会得到调整。

image.png

3.6.3 Cortex-M3 的双栈模型

之前已经提到Cortex-M3具有两个SP:MSP和PSP。实际使用哪个SP由控制寄存器的第1位控制(下面所说的CONTROL[1])。

当CONTROL[1]为0时,线程模式和处理模式都会使用MSP(见图3.16)。按照这种设计,主程序和异常处理共用相同的栈存储空间,这也是上电后的默认设置。

image.png

当CONTROL[1]为1时,线程模式使用PSP(见图3.17)。按照这种设计,主程序和异常处理可以使用独立的栈存储区域。这样用户程序的栈出现错误时,就不会破坏OS使用的栈了(假定用户程序只运行在线程模式,OS内核运行在处理模式)。

image.png

在这种情况下,应该注意的是,自动压栈和出栈机制将会使用PSP,不过异常处理中的栈操作会使用MSP。

也可以直接对PSP和MSP进行读/写操作,而无须考虑R13代表的含义。假定当前处于特权等级,你可以这样访问MSP和PSP的值:

image.png

一般来说,由于栈存储可能会用于存储局部变量,我们不建议在C函数中改变当前选定SP的值。要用汇编访问SP,可以使用MSR和MRS指令:

image.png

通过MRS指令读出PSP的值后,OS可以读出用户应用程序栈中的数据(如SVC操作前的寄存器内容)。另外,OS可以改变PSP指针数值,比如多任务系统上下文切换期间。

3.7 复位流程

在退出复位后,处理器会从存储器中读取两个字:

  1. 地址0x00000000:R13的初始值(SP)。
  2. 地址0x00000004:复位向量(程序执行的起始地址,LSB应该置1表示Thumb状态)。

image.png

这点同传统的ARM处理器不同,之前的ARM处理器从0x0地址开始执行程序,另外,之前的ARM设备中向量表为指令(你必须在此处放入一个跳转指令,异常处理则可以放在另外一个位置)。

对于Cortex-M3,MSP的初始值位于存储器映射的开始处,后面紧接着的是向量表,也就是向量的地址值(在程序执行过程中,向量表稍后可以被重新分配到另外一个地址)。另外,向量表的内容为地址值,而非跳转指令。向量表中的第一个向量(异常类型1)为复位向量,这是在处理器复位后读取的第二块数据。

由于Cortex-M3的栈操作为满递减的(存储前SP减小),SP的初始值应该置为栈顶后的第一个存储器地址。例如,若栈存储区域的范周为0x20007C00到0x20007FFF(1KB),栈的初始值应该置为0x20008000。

向量表在SP的初始值之后,第一个向量为复位向量。应该注意的是,在Cortex-M3中,向量表中的向量地址的最低位应置1,以表明它们为Thumb代码。由于这个原因,前面例子的复位向量为0x101,而启动代码是从0x100地址开始的(见图3.19)。取出复位向量后,Cortex-M3可以从复位向量地址处执行程序,并且开始正常操作。SP需要被初始化,这是因为复位后就可能会发生一些异常(如NMI),这些异常可能是需要栈存储的。

image.png

不同的开发工具在指定SP的初始值和复位向量时的方式可能不同,若要了解这方面更多的信息,最好参考开发工具提供的工程实例。第10章和第20章提供了ARM工具的一些例子,GNU工具链的例子则在第19章。

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

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

相关文章

# 在 Windows 命令提示符(cmd)中,可以通过以下方法设置长命令自动换行

在 Windows 命令提示符&#xff08;cmd&#xff09;中&#xff0c;可以通过以下方法设置长命令自动换行 1、点击 cmd 窗口左上角标题栏&#xff0c;选择【属性】。 2、在【属性】菜单中&#xff0c;依次点击【选项】&#xff0c;找到【编辑选项】下面的【自动换行】&#xff…

经纬度聚类:聚类算法比较

需求&#xff1a; 将经纬度数据&#xff0c;根据经纬度进行聚类 初始数据 data.csv K均值聚类 简介 K均值&#xff08;K-means&#xff09;聚类是一种常用的无监督学习算法&#xff0c;用于将数据集中的样本分成K个不同的簇&#xff08;cluster&#xff09;。其基本思想是…

OpenCV | 入门

OpenCV | 入门 安装 参考教程 基础知识 V G A 640 480 VGA 640 \times 480 VGA640480 H D 1280 720 HD 1280 \times 720 HD1280720 F H D 1920 1080 FHD 1920 \times 1080 FHD19201080 4 K 3840 2160 4K 3840 \times 2160 4K38402160 这些都表示了固定的像素…

AI-数学-高中52-离散型随机变量概念及其分布列、两点分布

原作者视频&#xff1a;【随机变量】【一数辞典】2离散型随机变量及其分布列_哔哩哔哩_bilibili 离散型随机变量分布列&#xff1a;X表示离散型随机变量可能在取值&#xff0c;P:对应分布在概率&#xff0c;P括号里X1表示事件的名称。 示例&#xff1a;

机器学习的指标评价

之前在学校的小发明制作中&#xff0c;在终期答辩的时候&#xff0c;虽然整个项目的流程都答的很流畅。 在老师提问的过程中&#xff0c;当老师问我recall,precision,accuracy等指标是如何计算的&#xff0c;又能够表示模型的哪方面指标做得好。我听到这个问题的时候&#xff…

使用FPGA实现串-并型乘法器

介绍 其实我们知道&#xff0c;用FPGA实现乘法器并不是一件很简单的事&#xff0c;而且在FPGA中也有乘法器的IP核可以直接调用&#xff0c;我这里完全就是为了熟悉一些FPGA的语法然后写了这样一个电路。 串-并型乘法器模块 从字面上看&#xff0c;串-并乘法器就是其中一个乘数…

深入学习Redis(1):Redis内存模型

Redis的五个对象类型 字符串&#xff0c;哈希&#xff0c;列表&#xff0c;集合&#xff0c;有序集合 本节有关redis的内存模型 1.估算redis的内存使用情况 目前内存的价格比较的高&#xff0c;如果对于redis的内存使用情况能够进行计算&#xff0c;就可以选用合适的设备进…

初识webpack项目

新建一个空的工程 -> % mkdir webpack-project 为了方便追踪执行每一个命令&#xff0c;最终产生了哪些变更&#xff0c;将这个空工程初始化成git项目 -> % cd webpack-project/-> % git init Initialized empty Git repository in /Users/lixiang/frontworkspace/…

多级留言/评论的功能实现——SpringBoot3后端篇

目录 功能描述数据库表设计后端接口设计实体类entity 完整实体类dto 封装请求数据dto 封装分页请求数据vo 请求返回数据 Controller控制层Service层接口实现类 Mapper层Mybatis 操作数据库 补充&#xff1a;返回的数据结构自动创建实体类 最近毕设做完了&#xff0c;开始来梳理…

https自签名ssl证书生成流程

准备工作&#xff1a; 0.安装完整版的openssl openssl下载官网 安装到C:\OpenSSL32&#xff0c;也可以安装到其它盘&#xff0c;不要包含空格和中文 打开openssl.exe所在目录如:C:\OpenSSL32\bin&#xff0c;输入cmd.exe打开cmd控制台 1.创建ca文件夹 ,证书文件夹 mkdir …

二维泊松方程(三角形区域)Matlab有限元编程求解|案例源码+说明文本

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

【Linux 进程】 自定义shell

目录 关于shell 1.打印提示符&&获取用户命令字符​编辑 2.分割字符串 3.检查是否为内建命令 cd命令 export命令 echo命令 1.输出最后一个执行的命令的状态退出码&#xff08;返回码&#xff09; 2.输出指定环境变量 4.执行外部命令 关于shell Shell 是计算机操…

C语言数组介绍

文章目录 一、数组的概念二、一维数组1.一维数组的创建2.一维数组的初始化3.数组的类型4.一维数组的使用5.一维数组在内存中的存储6.sizeof计算数组元素个数 三、二维数组1.二维数组的概念2.二维数组的创建3.二维数组的初始化4.二维数组的使用5.二维数组的输入和输出6.二维数组…

【教学类-50-09】20240505“数一数”图片样式09:数一数(几何图案——透明颜色重叠+纯黑边框+黑框粗细)

背景需求&#xff1a; 【教学类-50-03】20240408“数一数”图片样式03&#xff1a;透明图形与边框不相交&#xff0c;透明图形和其他透明图形重叠-CSDN博客文章浏览阅读867次&#xff0c;点赞28次&#xff0c;收藏25次。【教学类-50-03】20240408“数一数”图片样式03&#xf…

银行ETL-监管报送

1104报表 1104报表主要包括&#xff1a;资产负债&#xff0c;表外业务、流动性风险、贷款质量、投向行业和地区、重点客户等。 1104报表分类 普通报表、机构特色类报表。 反洗钱 大额交易、可疑交易。标签分类&#xff1a;疑似犯罪、疑似毒品、疑似传销。 反洗钱—接口报…

tomcat+maven+java+mysql图书管理系统2-完善项目结构,添加相关依赖

1.创建java目录 接着选择java&#xff0c;回车&#xff0c;则创建成功&#xff0c;成功后在左侧栏能看见 2.修改pom.xml文件,(添加依赖) <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…

pandas读取文件导致jupyter内核崩溃如何解决

读取execl文件出现以下问题: str_name "D:\\cao_use\\2017_2021(new).xlsx" train_df pd.read_excel(str_name, usecols[0])崩溃的指示图如下所示: bug原因:读入的文件太大&#xff0c;所需时间过长&#xff0c;在读取的过程中&#xff0c;使用中断按钮暂停会直…

mac监听 linux服务器可视化(Grafana+Promethus+Node_exporter)

Grafana和promethus(普罗米修斯)的安装和使用 监控系统的Prometheus类似于一个注册中心&#xff0c;我们可以只需要配置一个Prometheus,而在其他服务器&#xff0c;只需要安装node_exporter,它们的数据流转就是通过exporter采集数据信息&#xff0c;然后告诉prometheus它的位置…

AI视频教程下载:用 ChatGPT 和 WordPress 创建赚钱网站

您是否有兴趣开设网站&#xff08;博客&#xff09;&#xff0c;但不知道从何入手&#xff1f; 或者您已经开设了网站&#xff08;博客&#xff09;&#xff0c;但难以从中获利&#xff1f; 别找啦&#xff01; 本课程旨在教授您使用 WordPress 创建成功盈利网站&#xff08;博…