总线、中断控制器和 DMA
总线、中断控制器和 DMA
总线、中断控制器和 DMA
(1) 我们不想造一台 “设备定死” 的计算机
接入更多 (甚至
未知
) 的 I/O 设备
想卖大价钱的 “大型机”:IBM, DEC, ...
车库里造出来的 “微型机”:名垂青史的梦想家
IBM PC/AT: ISA (Industry Standard Architecture) 总线
Apple II: 50-pin slot connector (Apple II Bus)
总线、中断控制器和 DMA
总线:一个特殊的 I/O 设备
提供设备的 “虚拟化”:
注册
和
转发
把收到的地址 (总线地址) 和数据转发到相应的设备上
例子: port I/O 的端口就是总线上的地址
IBM PC 的 CPU 其实只看到这一个 I/O 设备
这样
CPU 只需要直连一个总线
就行了!
今天 PCI 总线肩负了这个任务
总线可以桥接其他总线 (例如 PCI → USB)
lspci -tv 和 lsusb -tv: 查看系统中总线上的设备
概念简单,实际非常复杂……
电气特性、burst 传输、中断、Plug and Play
总线、中断控制器和 DMA
总线:名场面
总线、中断控制器和 DMA
(2) CPU:只有一根中断线
总线、中断控制器和 DMA
我们需要一个 “仲裁器”
收集各个设备中断,并选择一个发送给 CPU
并且完成对设备的应答
例子
Intel 8259 PIC
programmable interrupt controller
可以设置中断屏蔽、中断触发等……
APIC (Advanced PIC)
local APIC: 中断向量表, IPI, 时钟, ……
I/O APIC: 其他 I/O 设备
总线、中断控制器和 DMA
(3) 解放 CPU 算力
操作系统:写入 1 GB 的数据到磁盘
即便磁盘已经准备好,依然需要非常浪费时间的循环
out 指令写入的是设备缓冲区,需要去总线上绕一圈
cache disable; store 其实很慢的
for
(
int
i =
0
; i <
1
GB /
4
; i++) { outl(PORT, ((u32 *)buf)[i]); }
如果是多处理器系统?
那就把 write_disk 线程扔到另一个 CPU 吧
总线、中断控制器和 DMA
Direct Memory Access (DMA)
加一个通用处理器太浪费,不如加一个简单的
DMA:
只能执行 memcpy(ATA0, buf, length); 的处理器
支持的几种类型的 memcpy
memory → memory
memory → device (register)
device (register) → memory
实际实现:直接把 DMA 控制器连接在总线和内存上
Intel 8237A
今天:PCI 总线支持 DMA
sudo cat /proc/iomem