使用端口映射I/O时是否使用虚拟内存?

问题描述:

如果我有一个内存映射I/O设备,并且我想写入位于地址0x16D34的此设备的寄存器,则0x16D34地址实际上是一个虚拟地址,并且CPU会先将其转换为物理地址,然后将数据写入物理地址。使用端口映射I/O时是否使用虚拟内存?

但是,端口映射I/O设备(例如:串行端口)如何,所以如果我想写一个位于地址0x3F8的串行端口的寄存器,是0x3F8地址的物理地址或虚拟地址?


编辑:我在x86架构上。

+2

更详细的看起来像x86,而不是一个内存映射外设。这个特定的问题不会帮助你理解。你需要得到整个图片。一本关于个人电脑架构的好书应该是一本好书。你问什么?虚拟内存/内存映射**或** devicce驱动程序?他们是两种截然不同的方法! – Olaf

+0

@Olaf看起来不像外设,你的意思是地址0x16D34?这只是我给出的一个数字例子,它并不指向任何东西。 – Steve

+0

IO端口不是内存地址,因此您不能询问它们是物理还是虚拟。 – harold

x86/x86-64上的端口映射I/O(大多数其他现代体系结构甚至不支持它)发生在完全独立的地址空间中。这个地址空间不受内存映射的影响,所以没有虚拟端口地址,只有物理端口地址。必须使用特殊的inout指令来执行端口I/O,简单的内存访问(例如mov)不能访问这个单独的地址空间。基于特权级别的访问保护是可能的;大多数现代操作系统默认情况下阻止用户空间进程访问I/O端口。

有关详细信息,请参阅英特尔“英特尔®64和IA-32架构开发者手册:卷1”(chapter 18 as of this writing)的“输入/输出”一章。

请注意,在x86的早期阶段,每个设备中的端口地址都是硬连线的,包括ISA附加卡。如果幸运的话,该卡具有一组jumpers用于选择设备的有限可能的端口范围之一,以避免设备之间的范围冲突。之后,引入Plug & Play以在系统引导期间动态选择。 PCI进一步完善了这一功能,因此I/O BAR几乎可以通过操作系统和/或固件映射到0x0000-0xffff地址空间内的任何地方。由于其固有的限制,设计新硬件时,现在强烈建议不要使用端口映射I/O。

+0

当地址在总线上时,x86 CPU是否还包含一个引脚来选择内存或I/O?这是我记得的东西,但大学很多年前对我来说(来自[内存映射I/O](https://www.cs.umd.edu/class/sum2003/cmsc311/Notes/IO/mapped)。 html)):*“IN和OUT之间的唯一区别,以及从内存中加载和存储的是CPU上的单个引脚输出。如果地址总线上的地址是内存地址,则该引脚将被输出,例如0如果地址是I/O地址“*”,则输出1。 – jww

+0

@jww我对此表示怀疑,今天的CPU内置了内存控制器,所以有很多引脚直接连接到内存模块,不需要在那里寻址I/O。他们也有直接的PCI Express通道。 PCIe使用非常少的引脚,消息(包括地址和有效载荷数据)仅在一对导线(针对每个方向)上串行传输,以便使用差分信号。也许对于一些传统的外围设备,但它们可能在南桥。 – pmdj

看来你的问题将是内存映射I/O和端口映射IO之间的差异。处理器通常有两种连接外部设备的方法,即内存映射I/O或端口映射I/O。

存储器映射I/O

存储器映射I/O使用相同的地址空间,以解决存储器和I/O设备。所以当CPU访问一个地址时,它可能指向一部分物理RAM,但它也可以指I/O设备的存储器(基于Memory-mapped I/O on Wiki)。

您的第一个示例中的值0x16D34应该是虚拟内存,并且会映射到物理内存。 I/O设备也会引用相同的物理内存以允许从CPU访问。

端口映射的I/O

端口映射的I/O使用一个单独的,专用的地址空间,并通过一组专用的微处理器指令被访问。对于第二个示例中的0x3F8,它是特定于内存和I/O设备的自己地址的地址。这不是我们之前在内存映射I/O中提到的内存和I/O设备之间共享的地址。你可能会在Memory-mapped IO vs Port-mapped IO