据我所知,适用以下定义:
- I/O 端口是内存地址用作与外部设备(例如打印机)通信的接口。
- 物理端口(即连接器)是插入设备的物理接口。
从这个定义可以看出,它们是两个不同的东西。但是,这个(我的定义)正确吗?或者这实际上是一回事,物理端口有一个内存地址?
我从一本关于计算机架构的书上解释了前一个定义,但现在我读得越来越多,我渐渐感到困惑。我想我的定义可能是错误的,我误解了这本书。
如果答案能够简要解释一下 I/O 端口是如何使用的,我将不胜感激...我只是不明白。
答案1
I/O端口和物理端口有区别吗?
适用以下定义:
- I/O 端口是用作与外部设备(例如打印机)通信的接口的内存地址。
- 物理端口(连接器)是插入设备的物理接口。
您的定义基本上是正确的。
I/O 端口使用软件(设备)驱动程序使用物理设备(插入物理端口的设备)。
看输入/输出系统以获得更详细的概述。
答案2
“I/O 端口”实际上更多地属于软件领域,这源于 Intel x86 硬件的传统设计,其中内存和 I/O 端口之间存在实际差异。您可以将两个设备都放在地址总线上,当您想要与内存通信时,您会发出一个信号,该信号“关闭”I/O 端口并“打开”内存,如果您想与 I/O 通信,则反之亦然。内存和 I/O 有不同的寻址方案,因此软件也必须跟踪这一点。
内存和 I/O 需要共享数据总线的原因在于 16 位 CPU 上可用的地址空间有限(64k)。随着 CPU 的发展,数据总线增长到 32 位(4 GB)和 64 位(18 千万亿!),共享开销已不必要。
现在使用的 32 位和 64 位处理器都直接对内存和 I/O 进行寻址,将 I/O 设备映射到不同的地址区域。这种方法称为内存映射 I/O。
对于物理端口,I/O 端口和内存映射 I/O 都连接到硬件,该硬件进一步缓冲和格式化(即 RS-232)信号,然后将其发送至计算机背面的连接器。
答案3
I/O 空间/端口是 x86 特有的遗留产物。在过去,有多个不同的地址空间(您可能已经看到最近的趋势是共享内存地址空间以更好地共享 CPU/GPU 资源,例如在 PlayStation 4 和 Xbox One 中)用于寻址内存和寻址“I/O 外围设备”。
I/O 空间用于与“真实”硬件外围设备通信,例如串行端口或并行端口。通常,在 I/O 空间地址 0x3F8 处,系统上的第一个串行端口位于此处。要与此设备通信,您无需使用常规内存访问指令,而是发出 I/O 访问指令;例如,在 Linux 上,您将使用 outb()、outl() 或 outw(),具体取决于您打算使用的宽度。同样,这是一个完全不同的内存空间比系统内存映射。
随着 PC 和 x86 的成熟(即我们现在可以本地寻址 32 位及以上的内存),内存映射I/O 变得越来越普遍。现在,系统内存映射中的任意内存位置(例如从 0 到 0xFFFFFFFF)都可以动态映射到特定设备。PCI 设备将具有需要一定量内存或 I/O 空间的 BAR(基址寄存器)。因此,对内存地址 0x80000000 的简单读取/写入实际上可能映射到物理 PCI 设备,当您将“1”写入该位置时,该设备会翻转 LED。这是一个过于简单的说法,忽略了虚拟内存/每个进程地址空间的存在,甚至忽略了用户空间地址和内核空间地址。
因此总结在我看来,作为一名电气/计算机工程师,“IO 端口”是指 x86 架构中的一个位置输入输出内存映射到特定设备的空间。物理端口是计算设备上一些真实的、有形的连接器,可以是 USB、串行等。
举个有趣的例子,如果您还记得玩过《星球大战:黑暗力量》等老 DOS 游戏,您会记得设置 SoundBlaster Pro。您将设置诸如端口 220、IRQ 5、DMA 1 之类的参数。这告诉游戏您的声卡位于 0x220 的 I/O 空间中,使用 IRQ 通道 5(请记住,此时您没有高端 APIC,您可能有一个或两个 Intel 8259)和 DMA 通道 1。
答案4
我不同意你的说法。港口与物理接口相关联,例如 USB 端口、db-25 (SR-232) 连接器等。正如预期的那样,术语I/O 端口也经常被解释为“物理”输入/输出引脚。
- 一些参考资料:Atmel AVR 微控制器:汇编语言和 C 语言编写的 MEGA 和 XMEGA(第 218 页)和8051 微控制器的架构和编程(第 34 页)。
然而,这些I/O 端口或一组引脚,有相关的输入/输出寄存器,因此可以粗略地认为I/O 端口确实是一个内存地址。
下图中可以看到4 个 I/O 端口,您可以连接电缆。每个端口都有关联的输入/输出寄存器例如,引脚PB0
逻辑电平(图中第一个引脚)将取决于寄存器(DDRB
、PINB
和PORTB
)所选逻辑电平在该引脚的组合方式。输入/输出寄存器,例如DDRB
,有一个相关的内存地址您可以通过代码访问它并更改其逻辑值。
[图片链接]