跳转至

I/O 设备

系统架构

  • 一个典型系统的架构: CPU 通过某种内存总线或互联电缆连接到系统内存; 高性能 I/O 通过常规的 I/O 总线连接到系统; 外围总线将更慢的设备连接到系统 image.png

    [!question] 为什么使用这样的分层架构 因为物理布局与造价成本 越快的总线越短, 因此高性能的内存总线没有足够的空间连接太多设备, 并且, 在工程上高性能总线的造价非常高. 所以, 系统的设计采用了分层的方式, 可以让要求高性能的设备离 CPU 更近一些, 低性能的设备离 CPU 更远一些. 最大的好处就是可以在外围总线上连接大量的设备

标准设备

image.png - 设备 - 向其他部分展现的硬件接口: - 与软件一样, 硬件也需要一些接口, 让系统软件来控制它的操作 - 设备都有自己的特定接口以及典型交互的协议 - 内部结构: - 包含设备相关的特定实现, 负责具体实现设备展示给系统的抽象接口

标准协议

  • 一个典型的交互:
    While(STATUS == BUSY)
        ; // wait until device is note busy
    Write data to DATA register
    Write command to COMMAND register
        (Doing so starts the device and executes the commands)
    While (STATUS == BUSY)
        ; // wait until device is done with your request
    
  • 简单协议的好处: 简单且有效
    • 问题: 轮询的过程比较低效, 在等待设备执行完成命令时浪费大量 CPU 时间, 如果此时操作系统可以切换到下一个就绪进程, 就可以大大提高 CPU 的利用率

利用中断减少 CPU 开销

  • 向设备发出一个请求, 然后就可以让对应进程睡眠, 切换执行其他的任务
  • 当设备完成了自身操作, 会抛出一个硬件中断, 引发 CPU 跳转执行操作系统预定义好的中断服务, 或者是更简单的中断处理程序
  • 中断处理的时间线: image.png

    [!attention] 中断并非总是最佳方案 如果有一个非常高性能的设备, 处理请求的速度非常快, 通常在 CPU 第一次轮询时就可以返回结果, 此时如果使用中断, 反而会使系统变得缓慢, 因为切换到其他进程, 处理中断, 再切换回之前的进程代价不小. 因此, 如果设备非常快, 那么最好的办法是使用轮询. 如果设备比较慢, 那么采用允许发生重叠的中断更好. 如果设备的速度未知, 可以考虑使用混合策略, 先尝试轮询一小段时间, 如果设备没有完成操作, 此时在使用中断.

[!attention] 在网络场景中最好不要使用中断 网络端收到大量数据包, 如果每一个包都发生一次中断, 那么有可能导致操作系统发生活锁, 即不断处理中断而无法处理用户层的请求. 如, 假设一个 Web 服务器突然承受很重的负载, 在这种情况下, 偶尔使用轮询的方式可以更好的控制系统的行为, 并允许 Web 服务器先服务一些用户请求, 再回去检查网卡设备是否有更多的数据包到达. 另一个基于中断的优化是合并 (coalescing). 设备在抛出中断之前往往需要等待一小段时间, 在此期间, 其他请求可能很快完成, 因此多次中断可以合并为一次中断抛出, 从而降低处理中断的代价.