为什么USB不是中断驱动的?
让 USB 成为轮询机制而不是中断驱动机制的理由是什么?我可以得出一些推理的答案是:
- 将处理效率和粒度的控制权留给操作系统,而不是设备本身。
- 防止故障设备造成的“中断风暴”。
我发现网上的一些解释说这主要是因为USB设备的性质。它们大多是基于微控制器的系统,无法对较大的传输进行排队,因此需要较短的中断间隔,而如此短的中断间隔可能不是最有效的。这是真的吗?
难道还有其他原因吗?
What's the rationale behind making USB a polling mechanism rather than interrupt-driven? The answers I can come up with some reasoning are:
- Leave control of processing efficiency and granularity to OS, rather than the device itself.
- Prevent "interrupt storms" by faulty devices.
Some explanations on the net that I found say that it's mostly because of the nature of USB devices. They are mostly microcontroller-based systems which cannot queue larger transfers therefore require short interrupt intervals and such short interrupt intervals may not be the most efficient. Is that true?
Could there be other reasons?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
USB发展的首要前提是“廉价芯片”。这是通过使用轮询来完成的,从而减少了对更高仲裁协议的需求。
Firewire 确实允许来自设备甚至 DMA 的中断,但它的价格要昂贵得多。因此,USB 在低成本领域获胜,而火线则在低延迟/低开销/...领域获胜。由于历史,USB 或多或少获胜了。
The overarching premise of the development of USB was, "cheap chips". This was done, through the use of polling, which reduces the need for a higher arbitration protocol.
Firewire, which did allow for interrupts from the devices and even DMA, was much more expensive. So USB won in the low-cost field, and firewire in low-latency/low-overhead/... field. Due to history USB more or less won.
有三种方法可以避免总线上的数据传输冲突:
采用稍微复杂的总线管理协议。这样的协议必须相当复杂,因为当太简单时,它会使总线相当慢(参见令牌环,它相当简单,但效率低下)。然而,拥有复杂的协议会使所有组件变得昂贵,因为它们都需要管理逻辑并且需要充分了解总线的实际工作原理(请参阅 Firewire)。
根本不要回避它们,允许它们存在,但要检测并处理它们。这也有些复杂,总线无法保证任何速度或延迟,就好像不断发生冲突一样,吞吐量会下降,延迟会增加(请参阅没有交换机的以太网,请参阅 WiFi)。
拥有一个总线主控器来控制谁可以在何时使用总线以及使用多长时间。这是便宜的,因为只有主设备必须是复杂的,并且主设备可以提供有关速度或延迟的任何可能的保证。
(3)是USB的工作原理,甚至USB主芯片也不需要很复杂,因为主芯片通常是一台具有快速CPU的计算机,并且可以在软件中执行所有总线管理。
USB 设备芯片被转储为吐司。他们不需要了解公交车的细节。他们只需要寻找发给他们的数据包,这些数据包要么是控制数据包,例如请求元数据或选择配置,由主机发送的数据包,要么是来自主机的轮询请求,说“如果你有东西要发送,现在正是时候”。
为了确保主站按时轮询它们,他们根据请求提供了一个简单的描述表,该表解释了它们提供的端点、需要轮询的频率以及轮询时最多传输多少数据。主设备可以使用该信息来建立轮询时间表,以确保所有设备都按时轮询并获得总线足够长的时间以允许其最大传输大小。当然,这并非在所有情况下都是可能的。如果您连接了太多需要非常频繁轮询的设备并且总是想要发送大量数据,您的系统可能会拒绝添加新设备并出现错误,即无法再满足其轮询要求。然而这种情况在实践中很少见,USB 仅限于 127 个设备(集线器算作设备,主设备本身也算作设备)。
电源管理的工作原理类似。每个设备都会告诉主设备它需要多少功率,主设备确保总线仍然可以提供这么多功率,同时考虑到活动集线器。如果您连接另一个设备并且总线无法再为其供电,则添加该设备将失败并出现错误。
这使得总线系统相当复杂、强大且快速,但其组件甚至不需要真正的 CPU。最简单的 USB 芯片只是连接串行数据线(如内部 RS-232 总线或 I2C 总线)的桥接器,没有真正可配置的内容,并且它们无法运行软件或具有可以更新的固件。它们只是将传入的数据包放入缓冲区,然后通过串行总线逐位发送缓冲区内容,它们在另一个缓冲区中接收串行数据,并在轮询时返回缓冲区内容。至于告诉主机配置(包括设备和供应商 ID,以及人类可读的字符串),它们只需发送一个小型外部 EPROM 的内容。事情再简单不过了,但这样的芯片已经足以构建大量 USB 硬件。
There are three ways to avoid data transfer collisions on a bus:
Have a somewhat complex bus management protocol. Such a protocol has to be rather sophisticated, as when too simple, it will make the bus rather slow (see Token Ring, which is rather simple, yet inefficient). However, having a sophisticated protocol makes all components expensive as all of them require management logic and need full understanding of how the bus actually works (see Firewire).
Don't avoid them at all, allow them but detect and handle them. This is also somewhat complex and the bus cannot guarantee any speed or latency as if there are constantly collisions, throughput will fall and latency will raise (see Ethernet without switches, see WiFi).
Have one bus master that controls who can use the bus at which time and for how long. This is inexpensive, as only the master must be sophisticated and the master can give any possible guarantee regarding speed or latency.
And (3) is how USB works and not even the master USB chips need to be sophisticated as the master is usually a computer with a fast CPU and can perform all bus management in software.
USB device chips are dump as toast. They don't need to understand the nifty details of the bus. They just have to look for packets addressed to them which are either control packets, e.g. requesting meta data or selecting a configuration, data packets sent by the master, or poll requests from the master saying "if you have something to send, now is the right time".
To make sure the master polls them on time, they hand out a simple description table on request, that explains which endpoints they offer, how often those need to be polled, and how much data they will at most transfer when being polled. The master can use that information to build up a poll schedule that ensures that all devices are polled on time and get the bus for long enough to allow their maximum transfer size. Of course, this is not possible under all circumstances. If you connect too many devices that require very frequent polling and always want to send a lot of data, your system may refuse to add a new device with the error, that its poll requirements cannot be satisfied anymore. Yet that situation is rare in practice and USB is limited to 127 devices (hubs count as devices, so does the master itself).
Power management works in a similar way. Every device tells the master how much power it needs and the master ensures that the bus can still deliver that much, taking active hubs into account. If you connect another device and the bus cannot power it anymore, adding the device will fail with an error.
This allows a fairly complex, powerful, and fast bus system, yet with components that don't even need a real CPU. The simplest USB chips out there are just bridges to a serial data line (like an internal RS-232 bus or an I2C bus) and there is nothing really configurable and they cannot run software or have a firmware one could update. They just place incoming data packets into a buffer and then sent the buffer content bit for bit over the serial bus and they receive serial data in another buffer and return the buffer content when being polled. As for telling the master the configuration (including device and vendor IDs, as well as human readable strings), they simply send the content of a small external EPROM. Things cannot get much simpler than that yet such a chip is enough to build plenty of USB hardware already.
这似乎是反USB FUD(如恐惧-不确定-怀疑)。
原因是这大大简化了硬件级别的事情——例如不再发生冲突。 USB 是半双工的,以减少电缆中的电线数量,因此无论如何只有一个可以通信。
虽然 USB 在线路上使用轮询,但一旦您在软件中使用它,您就会注意到 USB 中有中断。唯一的问题是延迟略有增加 - 在大多数用例中可以忽略不计。由于轮询通常在硬件 IIRC 中实现,因此软件只有在有新数据时才会收到通知。
在软件层面,有所谓的“中断端点” - 你猜怎么着,每个 HID 设备都使用它们:鼠标、键盘和操纵杆都是 HID。
This seems to be anti-USB FUD (as in Fear-Uncertainy-Doubt).
The reason is that this simplifies things on the harware level quite a bit - no more collisions for example. USB is half-duplex to reducex the amount of wires in the cable, so only one can talk anyway.
While USB uses polling on the wire, once you use it in software you will notice that you have interrupts in USB. The only issue is a slight increase in latency - neglible in most use cases. Since the polling is usually realized in hardware IIRC, software only gets notified if there is new data.
On the software level, there are so-called "interrupt endpoints" - and guess what, every HID device uses them: Mice, Keyboard and Josticks are HID.