RISC-Vrisc-v架构学习笔记(架构初学)

Posted 普通网友

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RISC-Vrisc-v架构学习笔记(架构初学)相关的知识,希望对你有一定的参考价值。

Register

介绍

RISC-V架构提供31个用户可修改的通用(基本)寄存器,即x1到x31,以及一个额外的只读寄存器x0,硬连接到0。x0寄存器的一个常见用途是帮助将其他寄存器初始化为零。
共有31个通用寄存器。

其中7个是临时寄存器(t0t6)。

a0a7用于函数参数。s0s11用于保存寄存器或函数定义内。

一个堆栈指针,一个全局指针和一个线程指针寄存器。

一个返回地址寄存器(x1),用于存储函数调用的返回地址。

一个程序计数器(pc)。PC保存着当前指令的地址。

所有寄存器都可以作为通用寄存器使用

Stack Pointer Register(SP)

在RISC-V体系结构中,x2寄存器被用作栈指针(sp),并保存栈的基址。此外,栈基址必须对齐到4个字节。如果不这样做,可能会出现加载/存储对齐错误。

Global Pointer Register(GP)

RISC-V使用x3 (gp)寄存器将所有全局变量放置在指定的特定区域。x3寄存器将保存全局变量所在位置的基址。

Thread Pointer Register(TP)

在多线程应用程序中,每个线程可能有自己的私有变量集,称为“线程特定变量”。这组变量将由寄存器x4 (tp)指向。
因此,每个线程在其x4寄存器中都有一个不同的值。

Return Address Register(RA)

x1 (ra)寄存器用于保存子程序的返回地址。在执行子程序调用之前,x1设置为子程序的返回地址,通常为“pc + 4”。标准的软件调用约定使用x1 (ra)寄存器来保存函数调用的返回地址。

Argument Register(参数寄存器)

在RISC-V中,8个参数寄存器,即x10x17(对应a0a7)用于在子程序中传递参数。
在子程序调用之前,子程序的参数被复制到参数寄存器。在参数数量超过8的情况下使用栈。

Temporary Register(临时寄存器)

临时寄存器用于在指令执行期间保存中间值。在RISC-V中有7个临时寄存器(t0t6)。

Privilege mode


risc-v架构将特权等级分为三个M、S、U。
User Mode:简称U 通常运行应用程序
Supervisor Mode:简称S 通常运行操作系统
Machine Mode:简称M 用于管理安全执行环境,最高权限,必选,其他两种模式都是可选的。

三种模式可以互相切换

Control and Status Registers (CSRs)

Registers

CSR寄存器非常多,下图为一些经常使用到的寄存器

MSTATUS(Machine Status Register)

Machine Status Register(MSTATUS)寄存器详细描述了机器的状态,并帮助控制机器的状态。mstatus寄存器有几个位来控制机器的不同状态。
](https://img-blog.csdnimg.cn/9f13268940924d19a647e48642e09384.png)

MSTATUS包含许多可以读取和更新的字段。通过修改这些字段,软件可以做一些事情,比如启用/禁用中断和更改虚拟内存模型等。
mstatus.MIE:Machine- Mode interrupt enable,机器模式全局中断使能位
mstatus.SIE: Supervisor-Mode interrupt enable,管理员模式全局中断使能位
x IE:=1则使能全局中断,=0则关闭全局中断,其只能控制小于或等于x模式下的中断,比如SIE=0,M模式下的中断不受其影响。
mstatus.MPIE:Machine- Mode previous interrupt enable,机器模式先前中断使能位
mstatus.SPIE:Supervisor-Mode previous interrupt enable,管理员模式先前中断使能位
x PIE:保存在trap之前interrupt-enable(x IE)位的值。
mstatus.MPP:Machine- Mode previous privilege,机器模式先前特权模式
mstatus.SPP:Supervisor- Mode previous privilege,管理员模式先前特权模式
x PP:保存trap之前的特权模式。xPP字段只能持有最多x的特权模式,因此MPP是2位宽,SPP是1位宽。
mstatus.MPRV:MPRV (Modify PRiVilege)位修改有效特权模式,即加载和存储执行时的特权级别。当MPRV=0时,使用当前特权模式的转换和保护机制,加载和存储行为正常。当MPRV=1时,加载和存储内存地址被转换和保护,并应用字节顺序,就好像当前特权模式被设置为MPP。指令地址转换和保护不受MPRV设置的影响。如果不支持U-mode,则MPRV为只读0。
当使用mret从trap中返回。会根据MPP的值来确定返回的新的特权模式,然后硬件改写mstatus中的MPP=0,MIE=MPIE,MPIE=进trap前的MIE,并设置PC=MEPC。

MCAUSE(Machine Cause Register)

Machine Cause Register寄存器是一个mxlen位的读写寄存器。当一个trap被带入m模式时,mcause被硬件写入一个代码,指示导致该trap的事件。如果trap是由中断引起的,则设置mcause寄存器中的中断bit位。

MTVEC(Machine Trap Vector Base Address register)

MTVEC用于存储Trap处理程序的地址。就是存储中断向量表的基地址。


当MODE=Direct时,所有进入机器模式的trap都会导致pc被设置为BASE字段中的地址。当MODE= vector时,所有进入机器模式的同步异常都会导致pc被设置为BASE字段中的地址,而异步中断会导致pc被设置为BASE字段中的地址加上中断cause数的四倍。

MEPC(Machine Exception Program Counter)

它保存导致trap的指令的地址。

MIE(Machine Interrupt Enable Register)

中断使能寄存器,区别于mstatus.MIE作为全局控制,MIE是局部控制。

MEIE:M模式外部中断使能位
SEIE:S模式外部中断使能位
MTIE:M模式timer中断使能位
STIE:S模式外部中断使能位
MSIE:M模式软中断使能位
SSIE:S模式软中断使能位

MIP(Machine Interrupt Pending Register )

中断挂起寄存器,包含关于挂起中断的信息。
我的理解:当正在处理一个中断,并且mie关掉中断时,同时设置了mip,此时产生了另一个中断则其会被pending,则MIP里对应的中断信息会被记录。

MEIP:M模式外部中断挂起位
SEIP:S模式外部中断挂起位
MTIP:M模式timer中断挂起位
STIP:S模式外部中断挂起位
MSIP:M模式软中断挂起位
SSIP:S模式软中断挂起位

MSCRATCH

mscratch 寄存器用于机器模式下的程序临时保存某些数据。mscratch 寄存器可以提供一
种快速的保存和恢复机制。譬如,在进入机器模式的异常处理程序后,将应用程序的某个通
用寄存器的值临时存入 mscratch 寄存器中,然后在退出异常处理程序之前,将 mscratch 寄
存器中的值读出恢复至通用寄存器。

CSR Instructions

Register to Register instructions

在系统的两个寄存器上执行指定的操作,并将结果留在指定的寄存器中。

CSRRC

CSRRC:CSR Read and Clear Bits,用于清除CSR。
将之前CSR的值复制到目的寄存器,然后将CSR的一些选定位清除为0,rs1的值作为位掩码,用于选择CSR中哪些位需要清除(逻辑与 and)。
例子:
csrrc x1, mcause, x2 将之前的mcause读取到x1,并与x2逻辑与

CSRR

CSRR:CSR Read,用于读取CSR。
CSRR指令用于读取CSR的值。将CSR的前一个值复制到目标寄存器。这是一个原子读取操作。
例子:
csrr x1, mtvec 读取mtvec到x1

CSRRW

CSRRW:CSR Read and Write,用于读写CSR。
将CSR的前一个值复制到目标寄存器,源寄存器的值(rs1)被复制到CSR,这是一个原子写操作。要读取CSR而不写入它,源寄存器(rs1)可以指定为x0。要编写CSR而不读取它,目标寄存器(rd)可以指定为x0。这是一个原子操作。
简单来说就是rd是读CSR到rd中,rs1是将rs1的值写入到CSR。
例子:
csrrw x0, mtvec, x1 将x1中的值写入mtvec

csrrw x1, mtvec, x0 读取mtvec到x1
csrrw x1, mtvec, x2 读取之前mtvec到x1,将x2写入mtvec

CSRRS

CSRRS:CSR Read and Set Bits,用于设置CSR的位。
将CSR之前的值复制到目标寄存器,然后将CSR的某些位设置为0,rs1中的值用作位掩码,用于选择在CSR中设置哪些位(逻辑或 or)。
例子:
csrrs x1, mstatus, x2 读取mstatus到x1,并与x2逻辑或

Immediate Instructions

CSRRCI

CSRRCI:CSR Read and Clear Immediate
将之前CSR的值复制到目的寄存器,然后将立即数与CSR进行逻辑与操作,清除CSR指定的位。
例子:
csrrci x1, mie, 3 保存mie的值到x1中,并将mie与3按位与

其他的寄存器与上述寄存器到寄存器的指令同理

Trap

Exception

异常通常是同步的,并且总是与程序集指令相关联。异常可能在指令执行的任何阶段出现。例如,在指令解码阶段,硬件可能会检测到一个错误的操作码字段。这将触发一个“非法指令”异常。当异常发生时,硬件用相应的异常代码设置mcause寄存器。
pc被设置为trap处理程序的基地地址。异常代码有助于识别异常的类型。在RISC-V中可能的异常列在表中
Illegal instruction (非法指令异常):当程序试图执行任何非法指令时,会发生异常。例如,试图写入只读CSR寄存器将产生非法指令异常。
Instruction/Load/Store address misaligned (指令地址错位异常):当程序试图执行无条件跳转或执行目标地址不是4字节对齐的分支时,会发生异常。例如,执行一个起始地址为0x80000001的程序。这将在无条件跳转时生成一个指令地址错位异常。
Instruction/Load/Store access fault (访问异常):当程序试图执行加载指令以访问来自未对齐地址或非4字节对齐的地址的数据时,会发生异常。例如,试图访问一个数据段而没有正确对齐,就会导致这个异常。
Environment call (环境调用异常):当程序执行系统调用时发生此异常。需要使用RISC-V的ecall调用指令。调用指令还可以用于从低权限模式切换到高权限模式。指令:ecall
Break point :当程序执行程序中设置的断点以进入调试模式时,会发生异常。

Handle Exception

一旦发生异常,处理器将停止执行并将控制传递给trap处理程序。
在此过程中,处理器特权被设置为Machine模式,处理器使用异常代码设置mcause寄存器。mepc设置为发生异常前指令所在的pc。所有异常都首先出现在机器模式trap处理程序中。这适用于来自不同特权级别的异常。机器模式trap处理程序在机器模式中执行。在trap处理程序中,首先寄存器的上下文被保存在栈中。然后处理trap。在此之后,栈中保存的上下文将被恢复。通过这种方式,可以在不给执行流造成太多麻烦的情况下处理trap。

硬件如何跳转到trap处理程序 这是通过使用trap处理程序的物理地址设置mtvec寄存器来建立的。通常将mtvec中的值称为“Trap entry”。

我们有时可能不希望在Machine Mode中处理异常。我们可能想把它弄进去
管理员模式甚至用户模式。因此,可以将一些或所有trap“delegate”委托给较低的特权级别。

MRET:机器模式Trap处理程序返回(MRET)用于从正在机器模式中执行的Trap处理程序返回。
一旦trap服务和保存的上下文被恢复。可以调用mret指令。
这条指令基本上是告诉处理器将控制权传递回mepc寄存器中的地址。来自较低特权级别的异常。MRET指令将控制转移到该特权级别。状态寄存器的MPP字段将被引用,以确定返回到哪个模式(m, s,或u)。返回将通过将保存的程序计数器从mepc复制到程序计数器(pc)来实现。

Exception Registers

mie、mstatus、mepc、mtvec、mcause等。参考CSR章节。

Interrupt

中断是由外部源触发的异步事件。处理器可能倾向于处理或忽略中断。中断可以是软件中断,也可以是硬件中断。在RISC-V中断中,分为定时器中断(Timer Interrupts)、软件中断(Software Interrupts)和外部中断(External Interrupts)。外部中断也称为全局中断。定时器中断在core中处理。软件中断是处理器内部(核间中断)的,外部中断由PLIC模块处理。在本章中,我们将学习如何在RISC-V中处理定时器和外部中断。

Timer Interrupts

当一个单独的定时器电路指示一个预定的间隔已经结束时,timer interrupt就会产生。将中断当前正在执行的代码。定时器中断由操作系统处理,操作系统使用它们来实现时间片多线程。
mtime Register
是一个同步计数器。它从处理器上电开始运行,并以滴答数提供当前的实时时间。
mtimecmp Register
这个寄存器用于存储计时器中断将要发生的时间。
mtimecmp的值与mtime进行比较。当mtime值大于mtimecmp时,发生定时器中断。mtime和mtimecmp寄存器都是64位内存映射寄存器。

External Interrupts

External Interrupts外部中断来自处理器外部,这种中断是异步的,由外部源通过硬件产生,由处理器处理。例如,在嵌入式过程控制系统中使用的RISC-V处理器可能会接收来自各种要求采取适当行动的传感器的外部中断。这些中断由平台级中断控制器(PLIC)处理。PLIC的中断源是连接到SoC (IO, UART, SPI等)的设备。根据RISC-V规范,这些被称为全局中断源,每个中断源被PLIC优先排序并路由到核心。

Software Interrupts

Software Interrupts软中断是由在机器状态字中设置一个位引起的。在多核芯片中,运行在一个核上的线程需要向另一个核发送中断信号。

先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

大型网站架构学习笔记

前言

最近一直在拜读两本书:

1、李智慧老师的《大型网站技术架构 核心原理与案例分析》

2、曾宪杰老师的《大型网站系统与Java中间件实践》

看了并结合自己目前的工作进行了思考,感觉获益匪浅、受益良多,自己对大型网站的理解又有了不少的加深,下面分享一下自己的学习笔记。

 

学习笔记

1、大型网站架构的发展史(红字就是每一步发展历程的关键)

(1)从一个小网站发展起来,一台服务器,应用程序、数据库、文件等所有资源都在一台服务器上

(2)网站业务的发展,一台服务器逐渐不能满足需求,因此要将应用和数据分离,应用和数据分离后使用三台服务器:应用服务器、文件服务器和数据库服务器

(3)网站进一步发展,数据库压力太大导致访问延迟,因此使用缓存该改善网站性能(记住,使用缓存是改善网站性能的第一步),网站使用的缓存分为两种:缓存在应用服务器上的本地缓存和缓存在专门的分布式缓存服务器上的远程缓存

(4)使用缓存,数据库访问压力得到有效缓解,但是在网站访问高峰期应用服务器还是成为了整个网站的瓶颈。这种时候要理解,不要企图去更换更强大的服务器,对大型网站而言,不管多么强大的服务器,都满足不了网站持续增长的业务需求,因此可以通过增加服务器的方式改善负载压力,再通过负载均衡调度服务器,将来自用户浏览器的访问请求分发到应用服务器集群中的某台服务器上

(5)虽然使用缓存可以使大部分数据不走数据库,但是缓存没有命中、缓存过期的数据还是会走数据库,网站达到一定规模之后,数据库读写压力还是会很大,成为网站的瓶颈。此时可以使用数据库读写分离来改善数据库负载压力,应用服务器写数据走写库,应用服务器读数据走读库,目前大部分主流数据库都提供主从热备功能,通过配置两台数据库主从关系,可以将一台数据库服务器的数据更新同步到另一台服务器上

(6)随着网站业务继续发展,用户规模不断增大,由于中国复杂的网络环境,不同地区用户访问网站时,速度差别也极大。因此可以使用反向代理和CDN,一方面加快用户访问速度,另一方面减轻后端服务器的负载压力,因为反向代理和CDN的基本原理都是缓存

(7)数据库经过读写分离后,由一台服务器拆分为两台服务器,但还是不能满足网站业务量的需求,因此可以使用分布式数据库,主要拆分手段是业务分库,将不同的业务数据部署在不同的物理服务器上

(8)大型网站为了应对日益复杂的业务场景,可以使用分而治之的手段将整个网站的业务拆分成不同的应用,每个应用独立部署,可以通过超级链建立关系,也可以通过消息队列进行数据分发

大型网站发展到这里,基本上大多数的技术问题都得以解决

 

2、高性能网站的关键:控制住并发的量。只要能做到这点,很多棘手的数据问题也就不是什么问题了

 

3、不要企图通过技术解决所有问题,业务的问题也可以通过业务手段去解决

比如12306建立之初,0点售票,网站一下子要承受几千万的访问量,直接导致 12306这个网站崩溃,各路专业人士和分专业人士众说纷纭、出谋划策。但这仅仅通过技术能解决问题吗?所以,针对这个需求,12306不仅要改善它的技 术架构,也要调整它的业务架构,不要0点售票,在售票方式上引入排队机制、整点售票改为分时段售票,并发量控制住了,整个网站的性能就改善了

 

4、计算机软件发展的 一个重要目标和驱动力是降低软件的耦合性,事物之间关系越少,就越少彼此影响,越可以独立发展

 

5、异步架构是典型的生产者消费者模式

 

6、使用异步队列有几个好处

(1)提高系统的可用性

(2)加快网站的访问速度

(3)消除并发访问高峰

 

7、网站伸缩性就是指通过不断向集群中加入服务器的手段来缓解不断上升的用户并发访问压力和不断增长的数据存储需求

 

8、衡量架构伸缩性的指标

(1)是否可用多台服务器架构集群

(2)是否容易向服务器中添加新的服务器

(3)加入的服务器是否可以提供和原服务器无差别的服务

(4)集群中容纳的总服务器是否有限制

 

9、反应系统忙闲的重要指标Load

System Load也称为Load,即系统负载,指当前正在被CPU执行和等待被CPU执行的线程数之和,,是反映系统忙闲程度的重要指标。多核CPU下,完美情况 应该是所有CPU都在用,没有线程等待处理。Load值低于CPU数目,表示CPU有空闲,资源存在浪费;Load值高于CPU数目,表示进程在等待 CPU调度,资源存在不足

 

10、浏览器访问优化手段

(1)减少http请求,合并CSS、JS、图片,不要发起多次http请求去拿这些数据

(2)使用浏览器缓存,存储静态资源,Cache-Control、Expires、Pragma、Last_Modified都是和缓存的HTTP HEADER

(3)启用压缩,有效减低通信传输的数据量

(4)CSS放在上面、JS放在下面,因为JS下载会立即执行,可能阻塞页面加载速度

(5)减少Cookie传输

 

11、缓存使用的几点细节

(1)频繁修改的数据不要写缓存,一般读写比例至少2:1以上才会做缓存,即一次写入至少有两次以上的读取,像新浪微博这种,热门微博,一次写入可能会被读取数百万次,那是大大地合算

(2)如果访问没有热点,大部分数据的访问没有集中在小部分数据上,那么做缓存就没有意义,因为缓存有失效机制,大部分数据还没有被再次访问就被挤出缓存了

(3)容忍一定时间的数据不一致,除非数据更新时立刻通知缓存,不过这也会带来开销与事物一致性的问题

(4)使用分布式缓存集群以提高缓存可用性

(5)新启动的缓存没有任何数据,在重建缓存的过程中,系统性能与数据库负载都不太好,因此要根据项目、根据业务,将一部分数据在启动时就加载好,这就是缓存预热

(6)对缓存做无效参数并设置失效时间,避免不恰当的业务或恶意攻击频繁调用接口查询数据库,一旦某一个Key值数据库里面查不到数据就进入无效缓存,一段时间内再次访问这个Key值无数据返回

 

12、消息队列具有很好的削峰作用(前面提过),不过注意需要适当修改业务流程进行配合

通过异步处理,将短时间高并发产生的事物消息存储在消息队列中,从而可以削平高峰 期的并发事物。不过要注意点,由于数据写入消息队列后立即返回给用户,数据在后续的业务校验、写数据库等操作可能失败,因此在使用消息队列进行业务异步处 理后,,需要适当修改业务流程进行配合,如订单提交之后,订单数据写入消息队列,不能立即返回给用户订单提交成功,需要在消息队列的订单消费者进程真正处 理完该订单的,甚至商品出库后,再通过电子邮件或者SMS消息通知用户订单成功,避免交易纠纷

 

13、CDN和反向代理的基本原理都是缓存,区别在于CDN部署在网络提供商的机房,使用户在请求网站服务时,可以从距离自己最近的网络提供商机房获取数据;反向代理则部署在网站的中心机房,当用户请求到达中心机房时,首先访问的是反向代理服务器,如果反向代理服务器中缓存着用户请求的资源,就将其直接返回给用户。使用CDN和反向代理的目的是一样的:

(1)尽早返回速度给用户,加快用户访问网站的速度

(2)减轻后端服务器的负载压力

 

14、应用服务器集群的Session管理

单机环境 下,Session可由部署在服务器上的Web容器管理,在使用负载均衡的集群环境中,由于负载均衡服务器可能会将请求分发到集群任何一台应用服务器上, 所以保证每次请求依然能够获得正确的Session比单机时要复杂得多。集群环境下,Session管理有以下手段:

1、Session复制

在集群中的几台服务器之间同步Session对象,使得每台服务器上都保存着所有用户的Session信息,这样任何一台机器宕机都不会导致Session数据的丢失,而服务器使用Session时,也只需要从本机获取即可。

这种方案虽然简 单,从本机读取Session信息也很快,但只能使用在集群规模比较小的情况下。当集群规模较大时,集群服务器之间需要大量的通信进行Session复 制,占用服务器和网络的大量资源,系统不堪负担。而且由于所有用户的Session在每台服务器都有备份,在大量用户访问的情况下,甚至会出现服务器内存 不够Session使用的情况。

大型网站的核心应用集群就是数千台服务器,同时在线用户达到数千万,并不适用这种方案。

2、Session绑定

Session绑 定可以利用负载均衡的原地址Hash算法,负载均衡服务器总是将来源于同一IP的请求分发到同一台服务器。这样在整个会话期间,用户所有请求都在同一台服 务器上处理,即Session绑定在某台特定服务器上,保证Session总能在这台服务器上获取,这种方法又被称为会话粘滞。

但是 Session绑定的方案不符合对系统高可用的需求,因为一旦某台服务器宕机,那么该机器上的Session也就不复存在了,用户请求切换到其他机器后因 为没有Session而无法完成业务处理。因此虽然大部分负载均衡服务器都提供原地址负载均衡算法,但很少有网站利用这个算法进行Session管理

3、利用Cookie记录Session

早期的企业应用使用C/S架构,一种管理Session的方式是将Session记录在客户端,每次请求服务器的时候,将Session放在请求中 发送给服务器,服务器处理完请求后再将修改过的Session响应给客户端。网站没有客户端,但是可以利用浏览器支持的Cookie记录Session。

利用Cookie记录Session也有一些缺点:

(1)受到Cookie大小限制,能记录的信息有限

(2)每次请求和响应都携带Cookie,影响性能

(3)如果用户关闭Cookie,访问就会不正常

不过因为Cookie简单易用且可用性高,支持应用服务器的线性伸缩,而大部分应用需要记录的Session信息有比较小,因此事实上,许多网站或多 或少都会使用Cookie记录Session

4、Session服务器

利用独立部署的Session服务器(集群)统一管理Session,应用服务器每次读写Session时,都访问Session服务器。

这种解决方案事实上是将应用服务器的状态分离,分为无状态的应用服务器和有状态的Session服务器,然后针对这两种服务器的不同特性分别设计其架构。

对于有状态的Session服务器,一种比较简单的方法是利用分布式缓存、数据库等,在这些产品的基础上进行包装,使其符合Session的存储和 访问要求;如果业务场景对Session管理有比较高的要求,那么就要利用Session服务集成单点登录(SSO)、用户服务等功能,则需要开发专门的 Session服务管理平台。

 

以上是关于RISC-Vrisc-v架构学习笔记(架构初学)的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记bootstrap--整体架构

终于学完阿里架构师推荐413页微服务分布式架构基础与实战笔记

《企业应用架构模式中文版》学习笔记(转)

.NET 云原生架构师训练营(KestrelServer源码分析)--学习笔记

《游戏引擎架构》读书笔记1-游戏引擎中的C++

.NET 云原生架构师训练营(权限系统 代码实现 WebApplication)--学习笔记