操作系统导论习题解答(36. I/O Devices)

I/O Devices

带着问题学习:如何将I/O集成到系统中?一般机制是什么?如何使它们高效?

1. System Architecture

在这里插入图片描述
上图所示,I/O设备被分成三层。但是为什么需要将其分层?

最直接的原因:物理(physics)成本(cost)。高性能通道没有太多空间插入设备且设计总线的成本高。采用分层结构,使性能越高的通道离CPU越近。

当然,随着科技的发展,现今的系统结构又进一步提升了性能:
在这里插入图片描述
DMI:Direct Media Interface
USB:Universal Serial Bus
PCIe:Peripheral Component Interconnect Express
ATA:AT Attachment
SATA:Serial ATA
eSATA:external SATA

从ATA到eSATA,每一次改变都提升了性能。

2. A Canonical Device

在这里插入图片描述
从上图我们能看出一个设备有两个重要组成成分:外部接口(Interface)内部结构(Internals)

3. The Canonical Protocol

再看一下Figure 36.3。外部接口由三个寄存器组成:

  1. 状态寄存器(a status register):读取当前设备状态。
  2. 命令寄存器(a command register):通知设备执行确定任务。
  3. 数据寄存器(a data register):在操作系统和设备之间传输数据。

接下来看一些操作系统控制外设的操作协议:

while (STATUS = BUSY)
	;			// wait until device is not busy
Write data to DATA register
Write command to COMMAND register
	(starts the device and executes the command)
while (STATUS == BUSY)
	;			// wait until device is done with your request

上述基本协议简单且有效。但是,涉及一些低效且不方便之处

第一点就是while()循环效率非常低。它消耗了大量的CPU时间去等待设备完成任务,而不是转换到下一个进程使用CPU。

那么如何避免循环产生的CPU时间浪费?

4. Lowering CPU Overhead With Interrupts

解决上述问题的方案其实我们已经在前面学过了:中断(interrupt)。操作系统能发出一个请求,使循环进程进入睡眠状态,然后转换到另一个进程。

中断允许计算和I/O重叠,这是提升CPU利用率的关键。

看一下图更好理解:

在这里插入图片描述
上图不使用进程转换。进程1使用CPU(CPU中用1表示);进程1进入循环等待(CPU中用p表示部分都是CPU时间的浪费)。

在这里插入图片描述
上图使用进程转换。当进程进入等待状态时,进程开始运行(充分利用CPU)。

中断能提高CPU利用率。但是要注意一点:使用中断并不总是最好的解决方法。考虑一个情况,如果进行进程转换的开销比进程进入等待状态的自循环开销还大,那为什么要使用中断呢?

另一个不建议使用中断的地方是网络(networks)

还有一个基于中断的优化是合并(coalscing)。可以将多个中断合并成一个中断传递,从而降低了中断处理的开销。当然,等待时间太长会增加请求的延迟(鱼和熊掌不可兼得)。

5. More Efficient Data Movement With DMA

如下图所示:进程1运行一段时间(CPU标记为1),然后希望将一些数据写入磁盘。它将启动PIO(programmed I/O),该I/O必须使用CPU一次将一个数据从内存复制到设备(图中标记为c),复制完成后,I/O在磁盘上开始,然后进程2可以使用CPU(CPU标记为2)。
在这里插入图片描述
上图可以看出启动PIO就需要使用CPU,这就浪费了CPU时间。如何使PIO开销更低呢?

上述问题的解决方法就是DMA(Direct Memory Access)。DMA本质上是系统中非常特殊的设备,无需过多的CPU干预即可协调设备与主存之间的传输。

DMA工作过程如下图所示:当进程1需要使用I/O时,通过DMA将数据从内存复制到设备,此时CPU处于空闲状态,转换到进程2使用CPU。
在这里插入图片描述

6. Methods Of Device Interaction

前面说了这么多,我们还是没有说明一个问题:如何与外设进行交互?

经过长时间的研究,提出了两种主要的设备交互方法:

  1. I/O指令(instructions)。这是一种最古老的方法,不同的指令具有不同的优先级。
  2. 内存映射IO(memory-mapped I/O)。硬件设备寄存器就像存储位置一样可用。

这两种方法严格来说其实没有优劣之分,需要具体情况具体分析

7. Fitting Into The OS: The Device Driver

讨论最后一个问题:为了保持通用性,如何将每个都有特定接口的设备安装到操作系统中?

解决上述问题要使用一种古老的技术:抽象(abstraction)

不妨看一下下图:上层应用对下层应用是如何实现的毫不关心,而仅仅是使用下层应用提供的操作。
在这里插入图片描述
上图还显示了设备的原始接口(raw interface)。该接口使特殊应用程序直接读取或写入块,而无需使用抽象。

上图看到的封装(encapsulation)也可能有其缺点。如果某个设备具有许多特殊功能,但必须提供与内核其余部分的接口,则这些特殊功能不能使用。

8. Case Study: A Simple IDE Disk Driver

为了更深入一点,让我们来看一个例子:
在这里插入图片描述
IDE磁盘与系统之间有一个由4种类型寄存器组成的简单接口:

  1. 控制寄存器
  2. 命令寄存器
  3. 状态寄存器
  4. 错误寄存器

系统与设备交互的基本协议如下(假设已经被初始化):

  1. 等待驱动准备就绪(wait for drive to be ready)
  2. 向命令寄存器中写入参数(write parameters to command registers)
  3. 执行I/O(start the I/O)
  4. 数据传输(data transfer)
  5. 中断处理(handle interrupts)
  6. 错误处理(error handling)

上述这些协议大部分都能在xv6 IDE驱动程序中找到:

在这里插入图片描述

posted @ 2022-10-14 19:11  astralcon  阅读(90)  评论(0编辑  收藏  举报