1. 设备及其基本工作方式
-
设备也是数字电路: 设备(如键盘控制器、VGA 控制器)本质上也是数字电路,就像 CPU 一样。它们接收数字信号(命令字)并按照信号的含义工作。
-
设备的工作方式: 设备拥有自己的状态寄存器和功能部件,类似于 CPU 的寄存器和运算器。设备接收“命令字”(设备指令),进行译码和执行,从而完成特定的功能。
-
CPU 访问设备的目的: CPU 访问设备是为了进行输入输出 (I/O),包括:
- 读取数据 (输入): 从设备获取数据,如从键盘控制器读取按键扫描码。
- 写入数据 (输出): 向设备发送数据,如向显存写入颜色信息。
- 控制状态: 查询或设置设备的状态,如获取键盘状态、设置 VGA 分辨率。
-
CPU 与设备的接口:设备寄存器
CPU 通过访问设备内部的 寄存器 来与设备进行交互。设备寄存器充当 CPU 和设备之间的接口。 -
数据寄存器: 用于数据输入输出。
- 状态寄存器: 用于读取设备状态。
- 命令寄存器: 用于写入命令字,控制设备行为.
-
I/O 编址方式:
CPU 需要一种方式来寻址和访问设备寄存器,这就是 I/O 编址。常见的编址方式有两种: -
端口 I/O (Port-mapped I/O):
-
专用 I/O 指令: CPU 使用专门的 I/O 指令 (
in
,out
in x86) 访问设备. -
端口号: 设备寄存器的地址称为 端口号.
-
端口号分配: IBM PC 兼容机对常见设备端口号有专门规定.
-
x86
in
和out
指令示例:代码段
movl $0x41, %al ; 将数据 0x41 放入 AL 寄存器 movl $0x3f8, %edx ; 将端口号 0x3f8 放入 EDX 寄存器 outb %al, (%dx) ; 将 AL 寄存器的数据输出到端口 0x3f8
这段代码将数据
0x41
(字符 'A' 的 ASCII 码) 发送到0x3f8
端口(通常是串口的端口)。CPU 只负责数据传输,不关心设备如何处理数据. -
局限性:I/O 地址空间有限
端口 I/O 的 I/O 地址空间大小在指令集设计时就已固定,随着设备增多和功能复杂化,端口 I/O 的地址空间逐渐受限.
-
-
内存映射 I/O (Memory-mapped I/O, MMIO):
-
物理内存地址编址: 使用 物理内存地址 来给设备寄存器编号.
-
内存访问重定向: 将一部分物理内存地址的访问 重定向 到 I/O 地址空间,CPU 访问这些内存地址时,实际上访问的是 I/O 设备.
-
普通访存指令访问设备: CPU 可以使用 普通的访存指令 (如
mov
,load
,store
) 来访问设备寄存器. -
优点:I/O 地址空间无限
MMIO 利用物理内存地址空间进行编址,物理内存地址空间和 CPU 位宽不断增长,MMIO 不受 I/O 地址空间大小的限制. -
缺点:无法直接访问被映射的物理内存
被映射到 I/O 地址空间的物理内存无法通过正常方式直接访问,但现代 64 位计算机物理地址空间巨大,划出一部分用于 MMIO 几乎没有影响. -
现代计算机主流:
MMIO 成为现代计算机主流 I/O 编址方式,RISC 架构 (MIPS, RISC-V) 只提供 MMIO,PCI-e、网卡、x86 APIC 等主流设备也支持 MMIO. -
NEMU 中的 MMIO 示例:VGA 显存
NEMU 中物理地址区间[0xa1000000, 0xa1800000)
被映射到 VGA 显存.C
memset((void *)0xa1000000, 0, SCR_SIZE); // 清屏操作
这段 C 代码使用
memset
函数,直接向显存地址0xa1000000
开始的内存区域写入数据,实现清屏操作。程序员可以将 I/O 设备像普通内存一样访问,简化了驱动开发.
-
2. 状态机模型下的输入输出
-
设备的两部分:数字电路 (D) 和 模拟电路
-
数字电路 (D): 设备状态
设备内部也包含数字电路,其时序逻辑电路可以看作是设备数字电路部分的状态 D。计算机通过 端口 I/O 指令 或 内存映射 I/O (MMIO) 访存指令 来访问和修改 D. -
模拟电路:连接物理世界
设备还包含模拟电路,负责与物理世界交互。例如,键盘的模拟电路检测按键电容变化,并将按键信息写入键盘控制器的寄存器 (设备状态 D)。用户在物理世界中按键的动作,通过模拟电路影响设备状态 D.
设备是计算机和物理世界的桥梁。
状态机模型 | 状态机模型之外 S = <R, M> | D 计算机/程序 <----I/O指令----> 设备 <----模拟电路----> 物理世界 | |
-
-
扩展状态机模型:仅建模 I/O 指令行为
由于设备行为多样且受物理世界影响,对设备状态和行为进行精确建模非常困难。因此,状态机模型扩展 不将设备状态 D 加入到 S 中,而是 仅对输入输出相关指令的行为进行建模:
- 普通指令执行:
状态机按照 TRM 模型 进行状态转移 (基于指令改变寄存器 R 和内存 M 的值). - 设备输出指令 (如
out
, MMIO 写):- 状态机 仅更新 PC (程序计数器),寄存器 R 和内存 M 的状态保持不变.
- 设备状态 D 和物理世界会发生相应变化 (例如,向串口输出字符,VGA 显存写入像素信息).
- 设备输入指令 (如
in
, MMIO 读):- 状态机的转移会 “分叉”,变成 不确定的状态转移.
- 状态机转移到哪个新状态 取决于执行指令时设备的状态 D.
- 设备输入指令的状态转移“分叉”示例 (键盘控制器
in addr, r
)
假设程序执行指令
in addr, r
,从键盘控制器地址addr
读取数据到 CPU 寄存器r
.- 不确定性:
寄存器r
的值 不确定,取决于用户是否按键以及按了什么键.r
可能是0x01
: 读到 "按下扫描码为 1 的按键" 的信息.r
可能是0x81
: 读到 "释放扫描码为 1 的按键" 的信息.r
可能是0x00
: 没有任何按键信息.
- 影响后续程序:
不确定的状态转移会影响后续程序运行。例如,游戏程序会根据读取的按键信息来决定游戏逻辑. - 游戏响应逻辑:普通计算指令
游戏如何响应按键输入,仍然是通过 TRM 模型中的普通计算指令 实现,与输入输出本身无关.
总结:
从状态机微观视角来看,设备的输入输出都是通过 CPU 寄存器 进行数据交互的。输入输出对程序的影响体现在 输入指令执行时会发生一次不能提前确定的状态转移。这基本上就是程序眼中输入输出的全部. - 普通指令执行:
3. 通过内存进行数据交互的输入输出:DMA
- S =
交互:
端口 I/O 和内存映射 I/O 都是通过 寄存器 R 进行数据交互的. - 通过内存 M 交互:DMA (Direct Memory Access)
存在通过 内存 M 进行数据交互的 I/O 方式,称为 DMA (Direct Memory Access). - DMA 的优势:高性能
DMA 通常用于高性能设备,可以 直接在设备和内存之间传输数据,无需 CPU 寄存器中转,提高数据传输效率.