操作系统概念 说道:
在 I/O 期间,各种设备控制器在准备好提供服务时会引发中断。这些中断意味着
- 该输出已完成,或
- 输入数据可用,或者
- 已检测到故障。
中断是否用于表示输出已准备好或输入已完成?
如果不是,是否需要通过其他方式来表示?
答案1
您将 或 放在标题中是件好事,因为答案是肯定的。
也就是说,确切的答案取决于您所询问的确切中断。我们以 SPI 端口和 DMA 为例。 SPI 是双向串行接口。
例如,DMA 中断标记所谓的水位是很常见的。当 DMA 缓冲区已满、“几乎满”(例如 3/4)、“几乎为空”(例如 1/4)以及完全为空时,您将产生中断。
对于 SPI 端口,您将拥有两个 DMA 通道。一个通道将处理来自外部设备的数据,另一个通道将处理从计算机发送到设备的数据。
因此,当输出 DMA 通道中断指示缓冲区为空时,这意味着输出已完成。当输入 DMA 通道中断指示缓冲区不为空时,这意味着输入数据可用。
答案2
该输出已完成,或
中断[也]用于表示输出已准备好吗?
是的。
考虑写入串行端口设备。该设备有一个称为 FIFO 的接收缓冲区,用于存储少量数据,例如 16 字节。
两种情况下都可能会出现中断
- 缓冲区变空,输出为完全的。这是
tcdrain()
在Linux上实现的。据称“当更改影响输出的参数时应使用此功能”。例如,当您想要更改串行端口的“波特率”(频率)时,您可以使用它来等待,直到使用当前波特率传输所有缓冲数据。 - 一个字节已从缓冲区中传输出去。现在有可用空间。该设备现已准备好CPU 将另一个字节推入缓冲区。
输入数据可用,或者
中断[也]用于表示输入已完成吗?
或许。但我不确定这里有两个不同的东西,至少在我的例子中是这样。
考虑从串行端口设备读取。该设备有一个称为 FIFO 的传输缓冲区,用于存储少量数据,例如 16 字节。
当 FIFO 从输入中收集到至少一个字节时,设备会发送一个中断。例如,连接到 CPU 的线路上的电压可能会从低电压变为高电压。
CPU 可以通过从 IO 端口或 IO 内存读取来消耗缓冲区中的字节。
旁注:此类事务可能需要比从系统 RAM 读取时间更长的时间。为此,IO 设备必须在总线上插入“等待状态”。即,存在短暂的握手,其中在IO设备设置“数据就绪”位之前可能需要几个总线频率周期。当写入 IO 端口/IO 存储器时,等待状态同样适用。然而,等待状态仅用于覆盖不同设备之间的操作频率/延迟的已知差异。它们不用于等待外部输入或输出。这是因为它们阻止 CPU 继续执行任何事物别的。
因此,当输入可用时,会发出中断信号。如果您愿意,当 CPU 读入输入字节时,您可以说输入“完成”。但不需要中断来发出信号。正如不需要中断来发出内存读取完成的信号一样。
输入缓冲区已满的情况实际上看起来更像是错误情况 - 它表明缓冲区溢出。该情况确实可能被设备记录下来,从而允许操作系统检测到错误。但是,我认为没有理由专门针对溢出发送中断。因为当输入可用时,设备可能已经发送了中断。
答案3
当重要事件发生时,大多数现代设备确实会产生中断。
然而,中断的代价是昂贵的。它会阻止处理器当前正在执行的操作,强制其处理中断。如果你得到太多的中断,它实际上可以休息你的操作系统。我遇到过这样的问题,比如蓝牙中断太多(即每秒超过 700,000 次)。
在黑暗时代,在 Apple 2 上,你根本不会受到任何干扰。一切都是通过民意调查类型的计划完成的。您将读取 I/O 端口,并根据各个位知道是否读取新数据。例如,要从软盘加载一个字节,您将循环直到一个字节为负(设置了位 7):
$1
LDA 0xC030
BPL $1
请注意,在英特尔处理器(可能还有其他处理器)上,中断严重过载。换句话说,无论您收到 VBL 中断、USB 端口中断还是来自全新 SSD 驱动器的中断,所有这些都可能使用中断 0x20。然后,CPU 的工作就是确定需要服务哪一个或哪些。在最后一种情况下,即多个设备引发相同的中断同时地,您必须确保它们在您返回之前都得到服务,因为您不会再收到另一个中断(即大多数设备发送一个中断信号,它们在服务之前不会重复该信号)。
更详细的一点是,在处理一个中断时,CPU 会阻止更多中断(在 Intel 处理器上为STI
/ )。CLI
这意味着它可以完成当前中断的所有工作,然后最终它必须处理另一个中断。这确保了 I/O 数据处理的串行化。这就是为什么我们经常从设备获取相对少量的数据。这允许将数据放置在用户空间中,然后可以由任意数量的线程处理。在现代 CPU 上,每个特定中断都可以由单独的 CPU 处理。这允许并行处理多个中断。不过,从我到目前为止所看到的情况来看,您必须提前决定哪个 CPU 将处理哪个中断。它不会在 CPU 之间进行“乒乓”操作。