3.1 CPU内部结构与时钟与指令
CPU内部结构
- 总线
- 一些自定义部件
- 总线图
- 内存指令
- 执行流程:取指令,译码,执行
- pc做的事
- 内存地址寄存器
- 内存缓存寄存器
- 指令寄存器,译码第一步
- 指令寄存器传递地址到内存地址寄存器
- 指令MOV_A的过程(译码第二步)
- 第一条指令执行完毕
- 第三条指令的执行
- 第四条指令
- 第四条指令不同的执行流程
- 整体流程
内部数据总线
- 使用到的有8位寄存器(用于输入),4位寄存器(用于内存地址,只能寻址16个内存单元[2^4]),简化版加法ALU
- 寄存器带了时钟, 由时钟统一控制操作
- ALU不需要时钟, 输入端的寄存器由时钟控制
- 总线就是一根根传送电信号的线 -_-
- 内部的意思就是封装在CPU内部的 -_-
- 外部总线就是主板上的 _
- 反正总线,就是一堆线
- 但在任意时刻,只能由一个部件对其读/写,因此下面的所有部件都增加了 可写(WriteEnable) / 可读 (OutEnable,也可以叫可输出)
- 在下面的图中有数据总线和地址总线,见名知意, 数据总线传送数据, 地址总线传送地址 ;- )
- 注意,数据包含指令,都是二进制, 是数据还是指令由CPU本身去识别(x86,arm …) 下面的汇编指令是我自己模拟的
下面有CPU整个执行流程,由于没有控制单元,因此纯手工操作
一些CPU内部需要用到的部件
简化版加法ALU
- 图上的C是进位,目前恒为零即可
4位寄存器,用于内存地址
8位寄存器,用于输入
总线图
- 时钟使用按钮代替
- 时钟用于让所有的电路自动工作,每触发一次,所有的相连的寄存器就工作一次
- 总的来说时钟是一切电路自动化工作的源头
- 古代碾磨需要一头牛来转圈,牛跑的越快碾磨速度越快, 振荡器速度越快,频率越高
- 而时钟的取名我猜就是类似 , 下一时刻时钟吼了一句"大家一起干活!"(脉冲信号),让所有的相连的电路一起干活
- 时钟的另一个作用是编程中的术语来说就是同步
- 例如:
- mov 寄存器B,0x99;
- mov 寄存器A, 寄存器B
- 寄存器B中的值有没有准备好? 什么时候能执行mov操作?
- ip/Eip什么时候往下移动?
- 一旦有了时钟,就容易同步操作
从内存中读取指令
- 为简化汇编指令, 这里只使用4条指令来演示, 自己模拟的汇编指令
- 汇编指令一般都有 操作码 ,操作数 2个部分组成
- 操作码对应要做什么, 操作数对应要对这个数做什么操作,在这里操作数只能对内存地址寻址
操作码 | 操作码二进制 | 解释 |
---|---|---|
MOV_A | 1000 | 复制数据到寄存器A |
MOV_B | 1001 | 复制数据到寄存器B |
MOV_TO_ADDR | 1010 | 复制寄存器C的数据到内存地址 |
ADD | 1011 | 把寄存器A,B相加存放到寄存器C |
指令相关
- 为简化指令,每个操作码固定占用4位,操作数也占用4位, 一个字节即可存放
- 操作码放高4位,操作数放低4位
- 当前的寻址寄存器是4位,只能寻址16个地址线,因此对应操作数来说正好
- 注意这里的操作数只能是内存地址
指令举例
操作码 | 操作码二进制 | 操作数二进制 | 解释 | 内存数据 | 对应汇编伪指令 |
---|---|---|---|---|---|
MOV_TO_ADDR | 1010 | 0010 | 把寄存器C的数据复制到内存地址0010(0x02) | 10100010 | mov [0010], c |
MOV_A | 1000 | 1111 | 把内存地址0xF的数据复制到寄存器A | 10001111 | mov a,[0x0f] |
MOV_B | 1001 | 1101 | 把地址0x0D的数据复制到寄存器B | 10011101 | mov b,[0x0D] |
ADD | 1011 | 无 | ADD没有操作数,固定只会寄存器A+B,输出到寄存器C | 10110000 | add a,b; mov c,a |
- 下面内存中的4条指令是
指令二进制 | 指令解释 |
---|---|
10001010 | 把地址1010的数据加载到寄存器A |
10011111 | 把地址1111的数据加载到寄存器B |
10110000 | 把寄存器A,B相加存放到寄存器C |
10101111 | 把寄存器C的数据复制到地址1111处 |
取指令,处理指令(译码),执行
- 所涉及到的几个部件
- PC: 程序位置计数器, 由于当前内存中只有4条指令,因此特意把PC设置成2位的计数器,0000 ~ 0011,但内存地址寄存器是4位的,所以把高2位设置成0
- 内存地址寄存器 - MAR , 4位寄存器(最大寻址16字节)
- CPU指令寄存器 - IR , 8位寄存器
- 内存缓存寄存器 , 8位寄存器
- 外部内存 (外部是意思是 相对于 其他寄存器都是CPU内部的 ), 内存只有16字节
- CPU数据外部总线和内部数据总线,地址总线这3根线的位宽取决于相连部件的输出,例如:
-
- PC输出的位宽是4位,内部地址总线位宽则是4
-
- 内存输出的位宽是8位, 外部数据总线的位宽是8
- 下面分部说明每个部件要干的活
PC所做的事
- 2位的计数器,因为内存中只有4条指令
- 输出端连接CPU内部地址总线,传输到 内存地址寄存器
- 但内存地址寄存器输入端是4位的,因此把PC的高2位置0
- 告诉 内存地址寄存器, 当前需要去获取哪个位置(地址)
- 当前PC的计数为0,因此传递过去也是0
- 把当前计数器的位置输出到 内存地址寄存器
- 把自身+1, PC 所存放的永远是下一条指令的位置
- 如下图所示,一开始会打开PC的OE(out Enable), 打开内存地址寄存器的WE(Write Enable), 时钟一叫唤,他俩开始工作
- 接下去, 关闭其他状态, 开启PC的WE, 时钟一叫, PC自身+1
内存地址寄存器
- 此寄存器用于传递地址
- 输入端连接CPU内部地址总线,输出端连接CPU外部地址总线, 总线连接到内存
- 两种情况:
- 1.把PC告诉自己的地址输出到CPU外部地址总线所相连的内存
- 2.把指令寄存器输出的地址, 传输与CPU外部地址总线相连的内存(这一步下面的指令寄存器有说明)
内存缓存寄存器
- 这个寄存器与CPU内部数据总线相连, 也跟外部数据总线相连
- 这个内外相连的寄存器:
-
- 写入端: 外部数据总线能对其写入, 内部数据总线也能对其写入
-
- 输出端: 能输出到外部数据总线,也能输出到内部数据总线
- 下图所示:
-
- 从内存地址寄存器(地址0000,此地址由PC传递过来) 通过地址总线传送到内存
-
- 内存把对应的二进制数据 通过 外部数据总线 传送到 内存缓存寄存器
-
- 此时,缓存寄存器有了数据,接着会把数据传递到指令寄存器
-
- 当前获取的内存地址:0000 中的二进制是10001010 => 16进制0x8A
- 此二进制是一条汇编指令,上面说过
通过内存地址寄存器传输到内存,内存输出到外部数据总线,再传输进内存缓存寄存器
内存缓存寄存器通过内部数据总线传输到指令寄存器
指令寄存器
- 上面说过, 内存缓存寄存器 同时连接外部数据总线和内部数据总线
- 内存缓存寄存器 将把获取的数据传送到 指令寄存器
- 此时 指令寄存器 内含的数据:0x8A(10001010)
-
- 10001010对应的指令是MOV_A:把1010地址的数据传送到寄存器A
-
- 高4位1000 是 自己模拟的汇编指令:MOV_A, 把数据复制到寄存器A的操作码
-
- 由于我自己模拟的汇编指令, 低4位都是需要从内存地址处获取数据(非立即数),因此将再次把低4位 1010 传递给 内存地址寄存器
- 一旦指令寄存器获取数据后,开始译码,这是一条MOV_A指令,后面低4位地址需要再次获取,因此将把低4位传送到内存地址寄存器
- 下图所示,指令寄存器低4位(0-3位)输出到 CPU内部地址总线 进而 传递进 内存地址寄存器
指令寄存器将低4位传送到内存地址寄存器
传送动图
回到内存地址寄存器,外部内存,内存缓存寄存器
- 内存地址寄存器获取4位地址后再次通过外部地址总线传递到内存
- 内存将此地址的1个字节的数据通过外部数据总线传送到 内存缓存寄存器
- 内存缓存寄存器将又一次把数据通过 内部数据总线 传送到 指令寄存器
-
- 这次传送过程中, 内存地址寄存器将地址0x0A(1010)传送给内存
-
- 内存地址0x0A所存放的数据是:0x08
-
- 内存缓存寄存器此时还保留着上次的值:0x8A,经过外部数据总线传送进来后,数据变成了:0x08
将指令寄存器传送的地址,传送到内存地址寄存器,通过外部地址总线,传送到内存,再通过外部数据总线传送到内存缓存寄存器
内存数据
数据传递动图
指令MOV_A的过程(译码)
- 译码:根据指令,执行相对应的操作,在这就是需要把数据复制到寄存器A
- 根据上面流程, 此时 指令寄存器的高位 1000, 对应MOV_A, 地址:1010 对应的内存数据也传送到 内存缓存寄存器中
- 接下来就要开始执行指令了,把 内存缓存寄存器的数据通过内部数据总线传送到 寄存器A 中
- 注:内存缓存寄存器的输出端连接内部数据总线,也连接外部数据总线
内存缓存寄存器的数据传递到寄存器A
到此内存中的第一条指令执行完毕
内存地址 | 指令二进制 | 指令解释 | 执行完成 |
---|---|---|---|
0x00 | 10001010 | 把地址1010的数据加载到寄存器A | Yes |
0x01 | 10011111 | 把地址1111的数据加载到寄存器B | No |
0x02 | 10110000 | ADD | NO |
0x03 | 10101111 | 把寄存器C的数据复制到地址1111处 | NO |
- 第二条指令与第一条指令类似,除了内存地址和寄存器不同,其他一致
- 这里就省略第二条指令的执行流程
开始第三条指令的执行
- 先回忆下前面的流程, 第一条指令执行完后PC的值:1
- PC的特性是:永远指向下条指令位置
- 第二条指令开始时
-
- 先把PC传送到内存地址寄存器
-
- 然后PC自身+1, 此时PC的值:2
-
- 省略其他流程
-
- 地址1111(0x0f)的数据是0x01.因此寄存器B的数据是:0x01
- 当第二条指令执行完毕后PC的值:2,也就是指向了第三条指令: 10110000 => ADD
- 第三条指令简述步骤:
-
- PC输出-> 内存地址寄存器 -> PC +1
-
- 内存地址寄存器 -> 内存 -> 写入内存缓存寄存器
-
- 内存缓存寄存器 -> 指令寄存器
-
- 指令寄存器开始译码
-
- 译码:此时这是一条ADD指令,不需要再去传送地址,直接让寄存器A,寄存器B 传送到 8位ALU加法器 中
-
- 最后ALU输出的结果存放到寄存器C中
下图是执行完第二条指令的状态图
执行第三条指令,直到指令被放入指令寄存器中
指令寄存器开始译码并执行
开始第四条指令
- 第四条指令简述步骤:
-
- 这条指令后,PC将回归0, 意味着这条指令执行完后,又会重新回到第一条指令
-
- PC->内存地址寄存器 -> PC+1(溢出,PC此时又回到了0,PC是2位寄存器)
-
- 内存地址寄存器 -> 内存 -> 内存缓存寄存器
-
- 内存缓存寄存器 -> 指令寄存器
-
- 这是一条MOV_TO_ADDR指令:10101111(0xAF)
-
- 指令寄存器开始译码
-
- 译码:这是一条把寄存器C复制到内存地址的指令
下图是执行第四条指令,直到指令被传送到指令寄存器中
第四条指令的不同
-
- 这和之前的指令都不一样,之前的指令是读取内存,现在需要写内存
-
- 不仅需要指定内存地址,也需要把数据准备好,指定在哪个地址上写什么数据
-
- 内存缓存寄存器 即连接内部数据总线,也连接外部数据总线,因此需要把寄存器C的数据输出到 内存缓存寄存器中
-
- 对于内存地址的指定,就需要依靠由 指令寄存器分离的低4位传递到 内存地址寄存器中
-
- 需要准备好的寄存器有: 寄存器C, 内存缓存寄存器,指令寄存器, 内存地址寄存器
-
- 数据: 通过寄存器C 传递到内存缓存寄存器;
-
- 地址: 通过指令寄存器分离的低4位,传递到内存地址寄存器
-
- 在数据和地址准备好后, 写入进: 内存缓存寄存器,内存地址寄存器, 下图1
-
- 此时有了数据和地址, 需要再次往内存写入地址和数据,下图2
-
- 往内存写完后,又会循环到第一条指令(PC=0)
图1. 把数据和地址分别传送给内存地址寄存器,内存缓存寄存器
图2. 把内存缓存寄存器和内存地址寄存器的数据写入内存
整体流程,全程手动,老夫累了
- 0.step 0 , PC
-
- 清空状态(把其他开关全关了)
-
- 打开PC OE, 打开 内存地址寄存器 WE
-
- PC 输出位置(2位) 到 内存地址寄存器
-
- 清空状态
-
- 打开 PC WE, PC自身加1 (永远指向下一条位置)
- 1.step 1,内存地址寄存器传送地址,内存缓存寄存器获取数据
-
- 清空状态
-
- 打开 内存地址寄存器 OE, 打开 内存缓存寄存器 WE, 打开 内存 OE
-
- 通过 内存地址寄存器 传输地址到内存
-
- 内存收到的地址把此地址的一个字节(二进制不分[数据,指令])通过外部数据总线 传输到 内存缓存寄存器
- 2.step 2, 内存缓存寄存器把数据传送到指令寄存器
-
- 清空状态
-
- 打开内存缓存寄存器OE,打开指令寄存器WE,时钟一吼,立即传送到位
- 3.step 3,指令寄存器干活
-
- 清空状态
-
- 开始译码
-
- 拆分1个字节,高4位操作码,低4位操作数(内存地址)
-
- 如果操作码是ADD,则跳转到step 7
-
- 如果操作码是MOV_TO_ADDR,跳转到step 8
-
- 如果操作码是MOV_A,MOV_B则往下执行
-
- 把低4位的地址传送到 内存地址寄存器
-
- 打开内存地址寄存器WE,打开 指令寄存器OE,时钟一吼,低4位的地址就传送到了 内存地址寄存器
- 4.step 4, 执行一次step 1, 传递地址获取内存数据
-
- 执行一次step 1,此时 内存缓存寄存器中有了数据
-
- 这个时候根据指令本身来执行(译码),此时指令寄存器中的指令是1000,即MOV_A,因此需要把数据传送到寄存器A
- 5.step 5, 把数据传送到寄存器A
-
- 清空状态
-
- 打开 内存缓存寄存器的OE, 打开寄存器A的WE,时钟脉冲一到, 一个字节的数据通过 CPU内部数据总线传送到了寄存器A,一条指令执行完毕
- 6.step 6, 回到step 0
- 7.step 7, 执行ADD
-
- 清空状态
-
- 打开寄存器A,寄存器B的OE,打开ALU的OE,打开寄存器C的WE, 时钟一到, A+B的结果就被存放在了寄存器C
-
- ADD执行完毕,回到step 0
- 8.step 8, 执行MOV_TO_ADDR
-
- 清空状态
-
- 准备好数据与地址,打开指令寄存器OE,打开内存地址寄存器WE,打开寄存器C的OE, 打开内存缓存寄存器的WE,时钟一喊, 地址和数据都准备完成
-
- 清空状态
-
- 打开 内存地址寄存器OE, 打开 内存缓存寄存器OE,打开 内存WE (往内存的某个地址上写数据)
-
- 至此最后一条指令执行完毕
-
- 再次回到step 0, 此时PC:0,因此将循环往复的从头执行
相关文章:

3.1 CPU内部结构与时钟与指令
CPU内部结构 总线一些自定义部件总线图内存指令执行流程:取指令,译码,执行pc做的事内存地址寄存器内存缓存寄存器指令寄存器,译码第一步指令寄存器传递地址到内存地址寄存器指令MOV_A的过程(译码第二步)第一条指令执行完毕第三条指令的执行第四条指令第四条指令不同的执行流程…...

电机应用-直流有刷电机多环控制实现
目录 直流有刷电机多环控制实现 硬件设计 直流电机三环(速度环、电流环、位置环)串级PID控制-位置式PID 编程要点 配置ADC可读取电流值 配置基本定时器6产生定时中断读取当前电路中驱动电机的电流值并执行PID运算 配置定时器1输出PWM控制电机 配…...

Java常量池理论篇:Class常量池、运行时常量池、String常量池、基本类型常量池,intern方法1.6、1.7的区别
文章目录 Class常量池运行时常量池String常量池基本类型常量池Integer 常量池Long 常量池 加餐部分 Class常量池 每个Class字节码文件中包含类常量池用来存放字面量以及符号引用等信息。 运行时常量池 java文件被编译成class文件之后,也就是会生成我上面所说的 …...

module java.base does not “opens java.io“ to unnamed module
环境 如上图所示, Runtime version的版本是JAVA 17 项目所需要JDK版本为JAVA 8 解决...

鸿蒙原生应用/元服务开发-AGC分发如何配置签名信息
使用制作的私钥(.p12)文件、在AGC申请的证书文件和Profile(.p7b)文件,在DevEco Studio配置工程的签名信息,以构建携带发布签名信息的APP。 1.打开DevEco Studio,菜单选择“File > Project S…...
【HTML5-webscoket实时通信(web)】
websocket是什么? 就是用来创建网络聊天室,实时通信websocket的方法有哪些? https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets如何实现:(以下实现流程) 前端: // 直播中// 聊天web…...

如何在Android平板上远程连接Ubuntu服务器code-server进行代码开发?
文章目录 1.ubuntu本地安装code-server2. 安装cpolar内网穿透3. 创建隧道映射本地端口4. 安卓平板测试访问5.固定域名公网地址6.结语 1.ubuntu本地安装code-server 准备一台虚拟机,Ubuntu或者centos都可以,这里以VMwhere ubuntu系统为例 下载code serve…...

SAP Smartforms打印报错Error in spool C call : spool overflow
处理方式: SAP打印时提示: Error in spool C call : spool overflow (假脱机请求溢出,通俗一点打印池已满) 解决办法: SE38 首先运行程序RSPO1041 再运行RSPO1043,话不多说上图。...

SQL 中的运算符与别名:使用示例和语法详解
SQL中的IN运算符 IN运算符允许您在WHERE子句中指定多个值,它是多个OR条件的简写。 示例:获取您自己的SQL Server 返回所有来自’Germany’、France’或’UK’的客户: SELECT * FROM Customers WHERE Country IN (Germany, France, UK);语…...

3.2 CPU的自动化
CPU的自动化 改造1-使用2进制导线改造2根据整体流程开始改造指令分析指令MOV_A的开关2进制表格手动时钟gif自动时钟gif 根据之前的CPU内部结构改造,制造一个cpu控制单元 改造一 之前的CPU全由手动开关自己控制,极度繁琐,而开关能跟二进制一一对应, 开:1, 关:0图1是之前的, …...
深入理解@Resource与@Autowired:用法与区别解析
Resource: Resource 是Java EE提供的注解,也可以在Spring中使用。它是按照名称进行注入的,默认通过属性名(通常是类名的小驼峰命名方式)或者name属性来匹配。如果找不到符合名称的bean,则会抛出异常。在使…...

高级驾驶辅助系统 (ADAS)介绍
随着汽车技术持续快速发展,推动更安全、更智能、更高效的驾驶体验一直是汽车创新的前沿。高级驾驶辅助系统( ADAS ) 是这场技术革命的关键参与者,是 指集成到现代车辆中的一组技术和功能,用于增强驾驶员安全、改善驾驶体验并协助完成各种驾驶任务。它使用传感器、摄像头、雷…...

2 使用React构造前端应用
文章目录 简单了解React和Node搭建开发环境React框架JavaScript客户端ChallengeComponent组件的主要结构渲染与应用程序集成 第一次运行前端调试将CORS配置添加到Spring Boot应用使用应用程序部署React应用程序小结 前端代码可从这里下载: 前端示例 后端使用这里介…...

[计算机网络]运输层概述
虽然我自己也不知道写在前面和前言有什么区别..... 这个系列其实是针对<深入浅出计算机网络>的简单总结,加入了一点个人的理解和浅薄见识,如果您有一些更好的意见和见解,欢迎随时协助我改正,感激不尽啦. 最近心态平和了不少, 和过去也完全做了个割舍吧,既然痛苦和压力的…...

【分布式】分布式事务及其解决方案
目录 一、分布式事务二、分布式事务的解决方案1. 全局事务(1)DTP模型(2) 两阶段提交协议(2PC)原理二阶段提交的缺点 (3)三阶段提交协议(3PC)原理 2. 基于可靠…...

【文末送书】机器学习高级实践
2023年初是人工智能爆发的里程碑式的重要阶段,以OpenAI研发的GPT为代表的大模型大行其道,NLP领域的ChatGPT模型火爆一时,引发了全民热议。而最新更新的GPT-4更是实现了大型多模态模型的飞跃式提升,它能够同时接受图像和文本的输入…...

吉他初学者学习网站搭建系列(1)——目录
文章目录 背景文章目录功能网站地址网站展示展望 背景 这个系列是对我最近周末搭建的吉他工具类平台YUERGS的总结。我个人业余爱好是自学吉他,我会在这个平台中动手集成我认为很有帮助的一些工具,来提升我的吉他水平和音乐素养,希望也可以帮…...

qgis添加arcgis的mapserver
左侧浏览器-ArcGIS地图服务器-右键-新建连接 Folder: / 展开-双击图层即可...

关于「光学神经网络」的一切:理论、应用与发展
/目录/ 一、线性运算的光学实现 1.1. 光学矩阵乘法器 1.2. 光的衍射实现线性运行 1.3. 基于Rayleigh-Sommerfeld方程的实现方法 1.4. 基于傅立叶变换的实现 1.5. 通过光干涉实现线性操作 1.6. 光的散射实现线性运行 1.7. 波分复用(WDM)实现线性运…...
【HarmonyOS】ArkTS开发@Styles装饰器和@Extend装饰器详解
文章目录 HarmonyOS详解ArkTS详解ArkTS装饰器深度解析:@Styles、@Extend、和stateStyles@Styles装饰器:优雅的组件样式定义与重用@Extend装饰器:扩展原生组件样式的利器stateStyles:多态样式的应用示例场景:装饰器的联合使用进阶应用:动态样式与交互最佳实践:样式的组织…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

如何将联系人从 iPhone 转移到 Android
从 iPhone 换到 Android 手机时,你可能需要保留重要的数据,例如通讯录。好在,将通讯录从 iPhone 转移到 Android 手机非常简单,你可以从本文中学习 6 种可靠的方法,确保随时保持连接,不错过任何信息。 第 1…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...