我们之前的文章提到了操作系统的三个抽象,它们分别是进程、地址空间和文件,除此之外,操作系统还要控制所有的 I/O 设备。操作系统必须向设备发送命令,捕捉中断并处理错误。它还应该在设备和操作系统的其余部分之间提供一个简单易用的接口。操作系统如何管理 I/O 是我们接下来的重点。

不同的人对 I/O 硬件的理解也不同。对于电子工程师而言,I/O 硬件就是芯片、导线、电源和其他组成硬件的物理设备。而我们程序员眼中的 I/O 其实就是硬件提供给软件的接口,比如硬件接受到的命令、执行的操作以及反馈的错误。我们着重探讨的是如何对硬件进行编程,而不是其工作原理。

打开网易新闻 查看更多图片

I/O 设备

什么是 I/O 设备?I/O 设备又叫做输入/输出设备,它是人类用来和计算机进行通信的外部硬件。输入/输出设备能够向计算机发送数据(输出)并从计算机接收数据(输入)。

I/O 设备(I/O devices)可以分成两种:块设备(block devices) 和 字符设备(character devices)。

I/O控制方式

①程序直接控制方式

CPU向I/O模块发出读写指令,CPU会从状态寄存器中读取I/O设备的状态,如果是忙碌状态就继续轮询检查状态,如果是已就绪,就代表I/O设备已经准备好,可以从中读取数据到CPU寄存器中,读到CPU后,CPU还要往存储器(内存)中写入数据,写完后再执行下一套指令。

优点:实现简单。在读写指令之后,加上实现轮询检查的一系列指令即可。

缺点:CPU和I/O设备只能串行化工作,CPU需要一直轮询检查,长期处于忙等状态,CPU利用率很低。

②中断驱动方式

中断驱动方式的思想是允许I/O设备主动打断CPU的运行并请求服务,从而“解放”CPU,使得其向I/O控制器发送读命令后可以继续做其他有用的工作。I/O控制器从CPU接收一个读命令,然后从外围设备读数据,一旦数据读入到该I/O控制器的数据寄存器,便通过控制线给CPU发出一个中断信号,表示数据已准备好,然后等待CPU请求该数据。I/O控制器收到CPU发出的取数据请求后,将数据放到数据总线上,传到CPU的寄存器中。至此,本次I/O操作完成,I/O控制器又可开始下一次I/O操作。这样就使得CPU与I/O设备能够并行工作。

优点:与程序直接控制方式相比,在中断驱动方式中,I/O控制器会通过中断信号主动报告I/O已完成,CPU不再需要不停的轮询。CPU和I/O设备可并行工作,CPU利用率得到明显提升。

缺点:由于数据中的每个字在存储器与I/O控制器之间的传输都必须经过CPU,这就导致了中断驱动方式仍然会消耗较多的CPU时间。

块设备

块设备是一个能存储固定大小块信息的设备,它支持以固定大小地块,扇区或群集读取和(可选)写入数据。每个块都有自己的物理地址。通常块的大小在 512 - 65536 之间。所有传输的信息都会以连续地块为单位。块设备的基本特征是每个块都较为对立,能够独立地进行读写。常见的块设备有 硬盘、蓝光光盘、USB 盘

与字符设备相比,这块设备通常需要较少的引脚。

打开网易新闻 查看更多图片

块设备的缺点

基于给定固态存储器的块设备比基于相同类型的存储器的字节寻址要慢一些,因为必须在块的开头开始读取或写入。所以,要读取该块的任何部分,必须寻找到该块的开始,读取整个块,如果不使用该块,则将其丢弃。要写入块的一部分,必须寻找到块的开始,将整个块读入内存,修改数据,再次寻找到块的开头处,然后将整个块写回设备。

字符设备

另一类 I/O 设备是字符设备。字符设备以字符为单位发送或接收一个字符流,而不考虑任何块结构。字符设备是不可寻址的,也没有任何寻道操作。常见的字符设备有 打印机、网络设备、鼠标、以及大多数与磁盘不同的设备。

下面显示了一些常见设备的数据速率:

无论是CPU还是其他 I/O设备,它们都连接在总线上,CPU和设备都具有总线控制器,总线还有总线仲裁器,设备的总线控制器向总线仲裁器申请总线使用权,得到总线使用权后,设备的总线控制器向CPU的总线控制器发起数据传送请求。得到CPU的回应后,开始把数据放在总线上传送给CPU。这是早期的总线模型。你说的设备控制器大概就是指设备的总线控制器,驱动器大概特指磁盘的总线控制器吧。

现代计算机系统里的总线和接口协议繁多复杂。CPU与I/O设备通讯的总线就是我们熟知的PCIe总线,每个接在PCIe总线上的设备都有PCIe控制器,CPU的PCIe控制器往往是整个树型PCIe总线的根,CPU要访问哪个设备时,就会通过PCIe控制器与接在PCIe总线上的设备形成点对点的私有通道。PCIe总线经过某些桥接芯片可以变成另外的总线,比如SATA,USB之类的。进而与接在这些总线上的设备通信。

I/O控制器的功能

● 接收设备CPU指令:CPU的读写指令和参数存储在控制寄存器中

● 向CPU报告设备的状态:I/O控制器中会有相应的状态寄存器,用于记录I/O设备的当前状态。(比如1代表设备忙碌,0代表设备就绪)

● 数据交换:数据寄存器,暂存CPU发来的数据和设备发来的数据,之后将数据发给控制寄存器或CPU。

● 地址识别:类似于内存的地址,为了区分设备控制器中的各个寄存器,需要给各个寄存器设置一个特定的地址。I/O控制器通过CPU提供的地址来判断CPU要读写的是哪个寄存器。