cpu如何与外围设备通信?

DrS*_*ove 27 hardware cpu communication

我假设cpu可以直接访问主板的BIOS和RAM.(如果我错了,请纠正我)

但是cpu如何与硬盘,扩展卡,外围设备,其他BIOS等其他硬件进行通信?

我知道操作系统及其驱动程序,但它们是软件 - 它们在RAM中.cpu如何在硬件级别与所有这些硬件进行通信?它不仅限于主板的BIOS和RAM吗?

Joh*_*ley 41

在较旧的体系结构中,外围设备通过单独的机制访问,使用特殊的I/O指令进行内存访问.在x86上,有(并且仍然是!)"in"和"out"指令用于在CPU和外设之间传输字节.为外围设备提供地址,例如键盘为0x80.简化很多,做"在0x80"将从键盘控制器读取一个字节到CPU寄存器"AL".

在现代架构中,外设以与内存类似的方式访问:通过总线上的映射内存地址.您不应该将总线视为访问内存的方式.这是解决各个外设的一种方法,其中内存(RAM/DDR)只是一种类型.例如,您可能在地址0x00000000..0x7fffffff处有2GB的RAM.之后,您可能拥有0x80000000..0x80001fff的图形卡.总线控制器(PCIe或其他)知道哪个地址范围到哪个外设.

内存通常是特殊的,因为它可以被缓存,因此对内存的单独读/写往往不会直接转换为对RAM芯片的单独读/写.外设被标记为特殊 - CPU访问应该完全按照程序中的说明进入外设.

与外围设备通信的语言几乎是临时的,具体取决于设备.一般主题是外围设备被映射到内存中的某个位置(例如,如上所述为几KB的0x80000000),其中各个状态位和操作由不同的字(通常为32或64位)控制.一个神秘的0x80000000串口示例:

  • 将32位字'A'写入0x80000000,在其输出FIFO中排队字符'A'.
  • 将32位字0x1写入0x80000004,告知串口发送其队列.

同样,完全是为了举例而做的,但真正的串口(uart)并没有那么不同.

麻烦的是,由于虚拟内存,您实际上不会在现代操作系统中看到任何上述内存布局.上面的地址将被称为"物理存储器地址"(或总线地址) - 发送到总线的实际地址.而CPU则会看到虚拟内存地址.各个外围设备需要映射到虚拟地址空间.这有点难以解释,可能在另一个问题中最好,但关键是你不太可能通过现代操作系统中的实际物理地址访问外围设备.

  • 这是一个很好的答案.你认为哪种书可能在这个主题上更广泛和/或更深入? (6认同)
  • @JohnRipley是的,我同意Lavya的观点.请向我们推荐一些你学过这些先生的好消息来源. (4认同)

Hum*_*rro 8

接受的答案当然是准确的,但也许 DrStrangeLove 打算解决其他问题,或者至少,这个问题包含另一个答案。事实上,当有人问“外设如何在硬件层面与CPU通信?”时,我认为答案应该提到I/O模块的作用(比如大家都知道的I/O适配器)。强调这一点很重要,因为与 I/O 设备对话所需的部分逻辑嵌入在 I/O 模块中,从而在执行 I/O 操作时减少了 CPU 注意力的需要。在问题的上下文中,这听起来与我有关,因为它询问 I/O 操作的硬件方面,而适配器是抽象 I/O 设备固有特性的硬件部分,向 CPU(以及操作系统)隐藏它们的复杂性。例如,磁盘适配器隐藏磁盘的几何方面,使 CPU 无需运行旋转磁盘板所需的逻辑,定位柱面并等待正确的扇区通过读/写磁头下方。类似的推理适用于其他设备,如视频适配器、网卡等。简而言之,如果没有 I/O 模块,I/O 任务将使 CPU 不堪重负。引用 Stallings:如果没有 I/O 模块,I/O 任务将使 CPU 不堪重负。引用 Stallings:如果没有 I/O 模块,I/O 任务将使 CPU 不堪重负。引用 Stallings:

I/O 模块的功能是允许处理器以简单的方式查看各种设备。可以提供一系列功能。I/O 模块可以隐藏外部设备的时序、格式和机电细节,以便处理器可以在简单的读写命令以及可能的打开和关闭文件命令方面发挥作用。在其最简单的形式中,I/O 模块可能仍会将控制设备的大部分工作(例如,倒带)留给处理器可见。承担大部分详细处理负担的 I/O 模块为处理器提供高级接口,通常称为 I/O 通道或 I/O 处理器。非常原始且需要详细控制的 I/O 模块通常称为 I/O 控制器或设备控制器。I/O 控制器常见于微型计算机,而 I/O 通道用于大型机。

此外,正如 John Ripley 正确指出的,有一个 I/O 空间以与 RAM 相同的方式映射。实际上,外围设备可以被映射直接到存储器的地址空间(其被称为MMIO,存储器映射I / O),或在一个分开的寻址空间PMIO,端口映射的I / O,这也被称为“分离的我/O”,因为与 MMIO 不同,I/O 地址与计算机 RAM 的地址完全分开。这就是为什么您必须使用inout指令与使用 PMIO 的设备进行通信的原因)。

综上所述,无论是 MMIO 还是 PMIO 都将 I/O 设备视为内存位置——这是硬件如何处理 I/O 操作的本质,但这里还有一些进一步的细节值得一提,以便获得丰富的概念负载输入/输出。由于每个适配器都有一个有限的地址范围,我们必须理解这样的内存位置作为数据缓冲区,这意味着您一次只有几个字节(“数据块”)与设备进行通信。出于这个原因,CPU 不直接使用从这些内存位置读取的数据是很常见的:首先,通过相应的地址从 I/O 设备读取数据,然后将该数据存储到 RAM 中,并且只有然后CPU可以使用它。为了实现这一点,请考虑 CPU 必须执行的大型二进制文件:磁盘适配器有一个有限的缓冲区,以它的 I/O 寻址空间为界(注意我不是指适配器的内部缓冲区,而是指 CPU 看到的地址空间),因此适配器从磁盘读取一些数据并在缓冲区填满时通过中断警告 CPU;接下来,CPU 中断它正在执行的任何操作,读取缓冲区,将缓冲区的内容复制到 RAM 中,并向适配器发出信号,它可以继续从磁盘中获取更多数据。这个循环一直重复,直到二进制文件完全加载到 RAM 中。从那时起,读操作被宣布完成,文件最终可以被执行。所以适配器从磁盘读取一些数据并在缓冲区填满时通过中断警告 CPU;接下来,CPU 中断它正在执行的任何操作,读取缓冲区,将缓冲区的内容复制到 RAM 中,并向适配器发出信号,它可以继续从磁盘中获取更多数据。这个循环一直重复,直到二进制文件完全加载到 RAM 中。从那时起,读操作被宣布完成,文件最终可以被执行。所以适配器从磁盘读取一些数据并在缓冲区填满时通过中断警告 CPU;接下来,CPU 中断它正在执行的任何操作,读取缓冲区,将缓冲区的内容复制到 RAM 中,并向适配器发出信号,它可以继续从磁盘中获取更多数据。这个循环一直重复,直到二进制文件完全加载到 RAM 中。从那时起,读操作被宣布完成,文件最终可以被执行。

这个周期称为中断驱动I/O并且完全发生在硬件中(有一些操作系统支持来处理中断),但请注意还有另外两个选项来执行 I/O 操作。也可以使用所谓的 PIO(可编程 I/O),而不是使用中断机制,CPU 通过循环不断地汇集控制器,直到收集到所有所需的信息,逐块(当最后一个块被检索,循环结束)。中断驱动的 I/O 和 PIO 都浪费 CPU 时间(尤其是后者)并且很久以前就被直接内存访问 (DMA) 所取代,它允许 I/O 设备直接将其数据写入(或读取)到(或来自)按照 CPU 的指示从 RAM 中读取。由于它的池化特性,我相信 PIO 是完全在软件中实现的,但在这一点上我可能是错的。我必须指出的是,