DMA(Direct Memory Access,直接存储器访问)是一种高速 I/O 方式。DMA 控制器直接控制数据在 I/O 设备和内存之间传输,无需 CPU 逐字节干预。CPU 只在传输开始和结束时参与,数据传输期间可以做其他工作。
| 方式 | 数据通路 | CPU 干预粒度 | 适用设备 |
|---|---|---|---|
| 中断方式 | I/O → CPU 寄存器 → 内存 | 每传一个字/字节都需 CPU 介入 | 中低速 |
| DMA 方式 | I/O ↔ 内存(不经 CPU) | 整个数据块只干预一次(开始+结束) | 高速 |
1. CPU 向 DMA 控制器发送命令:
- 内存起始地址、传输数据长度、传输方向(读/写)、设备号
2. CPU 继续执行其他程序(DMA 接手总线)
3. DMA 控制器控制数据传输:
- 每次传输一个字/字节,发总线请求占用总线
- 数据直接在 I/O 设备与内存间传送
- 地址寄存器 +1,计数器 -1
4. 传输完成 → DMA 向 CPU 发中断请求
5. CPU 响应中断,处理传输结束
DMA 控制器
MAR(内存地址寄存器) ← 当前内存地址
DAR(设备地址寄存器) ← 设备端口地址
WC (字计数器) ← 剩余传输字数(补码)
CR (控制/状态寄存器) ← 传输方向、模式等
BR (总线请求) → 向仲裁器发请求
BG (总线授权) ← 接收仲裁器授权
IRQ(中断请求) → 传输完成后中断 CPU
数据缓冲寄存器 ← 暂存传输数据
| 寄存器 | 功能 | 初始值来源 |
|---|---|---|
| MAR | 当前内存地址 | CPU 设置 |
| WC | 剩余字数 | CPU 设置(补码) |
| CR | 控制信号 | CPU 设置 |
| DAR | 设备地址 | CPU 设置 |
DMA 传输期间,CPU 完全放弃总线控制权,直到传输结束才归还。
CPU: ────────|停止访问|────────────
DMA: |=========传输========|
DMA 每次只窃取一个总线周期传输一个字,然后归还总线给 CPU。
CPU: ──工作──|窃取|──工作──|窃取|──工作──
DMA: |传输| |传输|
DMA 和 CPU 各自使用总线的不同部分,或在时钟的不同相位访问,无需总线仲裁,效率最高,但需要特殊硬件支持。
1. DMA 发总线请求 BR 6. MAR ← MAR + 1
2. 仲裁器发总线授权 BG 7. WC ← WC - 1
3. DMA 将 MAR 地址送地址总线 8. 归还总线(BG 撤销)
4. DMA 发读命令(内存→数据总线)9. 若 WC ≠ 0,回到步骤 1
5. 数据从数据总线送到设备 10. 若 WC = 0,发中断请求
1. DMA 发 BR 6. MAR ← MAR + 1
2. 仲裁器发 BG 7. WC ← WC - 1
3. DMA 将 MAR 地址送地址总线 8. 归还总线
4. 设备数据送到数据总线 9. 若 WC ≠ 0,回到步骤 1
5. DMA 发写命令(数据总线→内存)10. 若 WC = 0,发中断请求
void setup_dma(int *buffer, int length, int dir) {
out(DMA_MAR, buffer); // 内存起始地址
out(DMA_WC, -length); // 字计数(补码)
out(DMA_CR, dir | DMA_ENABLE); // 控制命令
// 启动后 CPU 可以做其他事
}
DMA 和 CPU 共享系统总线,需要总线仲裁机制。通常 DMA 优先级高于 CPU(保证数据不丢失),但可通过编程调整。
CPU 性能损失 = DMA 占用的总线周期 / 总周期数
例:CPU 主频 1GHz,总线周期 100MHz
DMA 传输速率 100MB/s,总线宽度 32 位
DMA 占用率 = 100MB/s / (100MHz × 4B) = 25%
CPU 性能损失约 25%
支持不连续内存块的传输,DMA 描述符链表:
[地址1, 长度1] → [地址2, 长度2] → [地址3, 长度3] → NULL
DMA 控制器自动按链表传输,无需 CPU 干预
多个 DMA 通道独立工作,每个通道连接不同设备
通道间可并行传输
| 特性 | 程序查询 | 程序中断 | DMA | 通道 |
|---|---|---|---|---|
| CPU 干预 | 每字节 | 每字节 | 开始和结束 | 开始 |
| 传输单位 | 字节 | 字节 | 数据块 | 数据块 |
| CPU 利用率 | 低 | 中 | 高 | 最高 |
| 硬件复杂度 | 低 | 中 | 高 | 最高 |
| 适用速度 | 低 | 中 | 高 | 最高 |
| 灵活性 | 高 | 高 | 中 | 最高 |
通道是专用的 I/O 处理器,有自己的指令集(通道指令),可独立执行 I/O 程序。CPU 只需启动通道,通道自动完成全部 I/O,利用率最高。
| 类型 | 传输单位 | 复杂度 | 并发性 |
|---|---|---|---|
| 字节多路通道 | 字节 | 低 | 多个低速设备并行 |
| 数组多路通道 | 数据块 | 中 | 多个高速设备交替 |
| 选择通道 | 数据块 | 高 | 一次只服务一个设备 |
传输时间 = 数据量 / DMA 传输速率
例:传输 1MB 数据,DMA 速率 100MB/s → 10ms
CPU 占用 = 初始化时间 + 中断处理时间
(DMA 传输期间 CPU 可做其他工作)
总线带宽占用:
CPU 可用带宽 = 总线带宽 - DMA 带宽占用
例:总线带宽 400MB/s,DMA 占用 100MB/s → CPU 可用 300MB/s
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。