DMA(Direct Memory Access,直接内存访问)允许 IO 设备直接与主存交换数据,不需要 CPU 干预数据传输过程。
与中断方式的对比:
| 寄存器 | 作用 | 说明 |
|---|---|---|
| MAR(内存地址寄存器) | 存放主存地址 | 每传一个字自动 +1 |
| WC(字计数器) | 存放剩余传输字数 | 每传一个字自动 -1 |
| DR(数据缓冲寄存器) | 暂存传输数据 | 缓冲 IO 设备和总线之间的数据 |
| CSR(控制状态寄存器) | 控制 DMA 操作 | 传输方向、启动、中断允许等 |
IO设备 ←→ 数据缓冲寄存器(DR) ←→ 系统总线 ←→ 主存
↑
DMA控制器
┌───────────────────┐
│ MAR(地址) │
│ WC(字计数) │
│ CSR(控制状态) │
│ 地址译码/控制逻辑│
│ 中断逻辑 │
└───────────────────┘
阶段1:预处理(CPU完成)
CPU设置:
- 传输方向(读/写)
- 内存起始地址 → MAR
- 传输字节数 → WC
- 启动DMA
阶段2:数据传输(DMA完成)
每传一个字/字节:
- IO设备数据 → DR
- DR → 主存[MAR]
- MAR + 1
- WC - 1
- 若WC ≠ 0,继续
- 若WC = 0,传输结束
阶段3:后处理(CPU完成)
DMA发中断 → CPU响应
- 检查传输是否正确
- 进行数据后续处理
以从 IO 设备读取一个字为例:
时钟周期1:DMA向IO设备发出读命令
时钟周期2:IO设备将数据送到DR
时钟周期3:DMA申请总线(总线请求BR)
时钟周期4:CPU响应总线请求(总线应答BG)
时钟周期5:DMA将MAR的地址送到地址总线
时钟周期6:DMA将DR的数据送到数据总线,发写信号
时钟周期7:主存接收数据,MAR+1,WC-1
DMA传输期间:
CPU ←─────────────────────→ CPU不能访问总线
DMA ←████████████████████→ DMA独占总线
优点:控制简单,传输速度快
缺点:CPU长时间停顿,效率低
CPU 停顿时间:
$$T_{停顿} = n \times t_{字}$$
CPU执行指令:
T1 T2 T3 T4 T1 T2 T3 T4
──────────────────────────────────────
↑挪用 ↑挪用 ↑挪用
DMA: ──█───█───█──
CPU: ───────停──停──停──
DMA 在 CPU 不使用总线时传输,若 CPU 要用则 DMA 优先。
特点:
CPU 停顿时间:
$$T_{停顿} = n \times t_{周期}$$
CPU和DMA在时钟的不同相位使用总线:
相位1(CPU使用):地址译码、执行
相位2(DMA使用):DMA传输
无冲突,但需要更复杂的时序电路。
主存 ──数据──→ 总线 ──数据──→ DMA DR ──数据──→ IO设备
←地址── 总线 ←地址── DMA MAR
IO设备 ──数据──→ DMA DR ──数据──→ 总线 ──数据──→ 主存
←地址── DMA MAR → 总线
主存A ──数据──→ DMA ──读出比较──→ 主存B
用于内存校验
磁盘转速 7200RPM,每道容量 16KB,数据总线宽度 32 位(4B),总线频率 100MHz。用 DMA 读取 1 个磁道的数据。
DMA每次传输4B
每道需要传输次数 = 16KB / 4B = 4096次
每次传输占用总线时间 = 1个总线周期 = 1/100MHz = 10ns
方式1:停止CPU访问
传输时间 = 4096 × 10ns = 40.96μs
CPU停顿时间 = 40.96μs
方式2:周期挪用
CPU停顿时间 = 4096 × 10ns = 40.96μs(挪用的时间和上面一样)
但分散在整个传输过程中
CPU 执行指令平均时间 80ns,DMA 每 100μs 挪用一个总线周期(10ns)。
100μs内CPU可执行的指令数(无DMA) = 100μs / 80ns = 1250条
100μs内CPU因DMA停顿的周期数 = 1个周期
CPU被停顿的比例 = 10ns / 100μs = 0.01%
实际上DMA连续传输多个字:
若连续挪用4096个周期:
CPU停顿 = 4096 × 10ns = 40.96μs
CPU执行时间 = 100μs - 40.96μs = 59.04μs
CPU效率 = 59.04/100 = 59%
传输 1MB 数据,字长 4B。
中断方式:
中断次数 = 1MB / 4B = 262,144次
每次中断服务时间 = 5μs
CPU用于IO的时间 = 262,144 × 5μs = 1.31s
DMA 方式:
DMA设置时间 = 10μs
DMA中断处理 = 10μs
总CPU时间 = 10 + 10 = 20μs
对比:DMA 方式 CPU 占用时间仅为中断方式的 $20μs / 1.31s \approx 0.0015%$!
传输 64KB 数据,每字 4B。
需要传输的字数 = 64KB / 4B = 16K = 16384字
WC需要的位数 = ⌈log₂(16384)⌉ = 14位
若 WC 用补码表示,初始值 = -(16384) = 1100_0000_0000_0000₂。每传一个字 WC+1,WC 溢出(变为 0)时传输完成。
总线带宽 200MB/s,IO 设备速率 150MB/s,每字 4B。
DMA 每秒传输次数 $= 150MB/s / 4B = 37.5M$ 次/s
每次占用总线时间 $= 4B / 200MB/s = 20ns$
总线被 DMA 占用的比例 $= 37.5M \times 20ns / 1s = 75%$
剩余总线带宽给 $CPU = 25%$
┌──────────────────────────────────┐
│ DMA传输过程 │
│ │
│ CPU设置DMA → DMA传输 → DMA中断CPU│
│ (预处理) (数据传输) (后处理) │
│ │
│ CPU ←──── 可以执行其他程序 ────→ │
└──────────────────────────────────┘
DMA 传输期间 CPU 可以执行程序,但当 $WC=0$ 时 DMA 会中断 CPU。
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。