为什么我们需要内存映射IO?

Why do we need memory mapped IO?

为什么我们需要内存映射IO?根据我在 CS class 中学到的知识,MMIO 抽象出控制设备的具体指令。但是,如果设备的控制寄存器(以及地址 space 部分中的每个存储单元)取决于设备的品牌和型号,那么在抽象方面获得了什么?

从根本上说,要使 CPU 能够执行 IO,它需要一种向设备读取和写入数据的方法。有很多方法可以做到这一点,例如像 x86 上的 IN/OUT 这样的专用 CPU 指令。 MMIO 是另一种已证明在简化硬件设计方面很受欢迎的解决方案。

在典型的 CPU 上,所有内核都将连接到公共总线,该总线允许内核 read/write 连接到主内存和共享缓存。然而,总线对于数据的来源、目的地和内容是不可知的。因此,总线上的传输可以到达不同的内存控制器、不同的内核、缓存等。因此,硬件设计人员可以简单地将 IO 设备连接到该总线,并且最终可以通过与 RAM 相同的机制访问这些设备。这具有一些优势:

  • IO 硬件现在可以直接从 RAM 或其他 IO 设备中检索数据,而无需内核参与掌握周期
  • CPU 缓存硬件可以侦听 IO 生成的事务以保持缓存一致
  • 当数据在总线上移动时,CPU 可以执行有用的工作,而不是内核等待每个 load/store 完成。
  • IO
  • 的CPU不需要支持特殊指令

这些优势中的大部分在软件中都被掩盖了,因此我认为 MMIO 有利于硬件设计者。

每个设备都有某种内部寄存器,软件(设备驱动程序)使用这些寄存器来控制设备的状态、要求设备执行操作以及确定状态。

软件(设备驱动程序)可以通过两种主要方式访问设备的内部寄存器 - 通过将这些寄存器映射到 CPU 的物理地址 space(与映射内存的方式相同进入 CPU 的物理地址 space);并通过提供专用机制(例如 80x86 上的 IO 端口)。

了解advantages/disadvantages;最好考虑 CPU/s 和内存之间通信的性质。这种沟通需要非常快,因为一切都取决于它;并且(对于电子设备)"fast" 往往意味着简单,总线长度较短(由于电容和电阻等原因)并且负载最少(因为每个负载都会增加驱动总线所需的电流,这意味着更大的晶体管处理更高的电流,这意味着晶体管切换需要更多的时间)。当然,还有一些技巧可以使它更快,从缓存(可能还有缓存一致性)开始,预取和推测执行可以让 CPU 在等待数据时保持忙碌。

通过提供专用机制(例如 80x86 上的 IO 端口),一切看起来都不错;因为你会在高速内存总线和所有(慢得多的)东西之间分离。

如果我们在性能最关键的数据路径(CPU 和 RAM 之间)的中间弄得一团糟,这样软件(设备驱动程序)就可以使用内存访问设备的内部寄存器会怎样?映射 IO 代替?哦男孩...

一开始,您将研究缓存的一些主要复杂性(至少,某种方式可以说 "these area/s should be cached, and those area/s shouldn't be cached" 具有确定哪些访问 are/aren 未缓存的所有逻辑,及其增加的延迟);加上 CPU 本身的更多主要并发症(can/should 它尝试预取?Can/should 它推测性地执行了一个 read/write?加上更慢(负载更多时更长)and/or 处理更昂贵的总线 "who knows what device/s might get plugged in",可能会有一些额外的痛苦(等待状态等)来处理比内存慢得多的设备。这听起来像是一个非常糟糕的主意。

然而,事实证明很多设备都可以从直接访问内存总线中受益(使用总线 mastering/DMA 直接在设备和 RAM 之间传输数据;而不是内存映射 IO (

如果您查看历史记录(至少对于 80x86);您会发现从 "simple, primarily using IO ports" 逐渐转变为 "extremely complex, primarily using memory mapped IO"。

Why do we need memory mapped IO?

不,这不是绝对必要的(但如果您愿意接受 performance/complexity 后果,那就更好了)。