当你敲键盘的时候,为什么显示器会显示字符?
当我们第一次使用电脑的时候,你会觉得神奇吗?为什么我们在键盘上敲击或者使用鼠标进行点击,就能实现各种操作;为什么显示器会显示出这些图标?这些用户操作的背后,是谁在同一管理他们呢?
今天我们就来说说,这些看得见摸得到的人际交互设备与我们操作系统的输入输出系统的关系。
设备分类
首先,我们来对我们常见的输入输出设备大致进行分类:
- 块设备:每个块有自己的地址,信息存储在对应的块中,如硬盘
- 字符设备:没有结构也无法寻址,都是直接传递的字节流,如鼠标
- 网络设备:也就是我们常说的 socket,数据单位是网络包。
然后我们将开始一步步的探索:首先,我们计算机中的大脑(CPU)要控制这些设备,比如想要控制显示器显示数字,还需要接收来自一些设备的控制,如键盘的输入等。那么形形色色的设备都需要进行管理,我们的 “大脑” 就需要 “手” 来帮忙,这就是设备控制器。
设备控制器
键盘、鼠标、显示器…. 设备之间功能不同,为了统一管理,每个设备都有一个设备控制器。设备控制器可以帮助我们屏蔽不同设备之间的差异。
设备控制器有寄存器,这些寄存器用来与 CPU 进行通信,CPU 通过写入和读取这些寄存器来发送或接收数据。控制器是有三类寄存器:状态寄存器、命令寄存器、数据寄存器。
数据缓冲区 有时候,由于输入输出设备传输的数据会很大,为了避免频繁操作设备,中间有一个数据缓冲区,CPU 写入的数据会先到缓冲区,当数据满足一定条件后才会发送给对应的设备。
驱动
虽然有设备控制器来帮助我们来操作对应的设备,但是我们需要告诉去读写设备控制器的寄存器,这部分操作由于每个控制器不同,也是不同的,故继续抽象引入了我们经常听到的“驱动”。
不同的设备控制器控制方式不同,但驱动程序会提供统一的接口给操作系统来方便操作系统进行调用。
通用块层
抽象到这步还不够,由于不同块设备(如磁盘,机械硬盘等)有着不同的设备驱动程序,为了让文件系统有统一的读写块设备接口,针对块设备还要继续抽象,屏蔽不同类型块设备的驱动之间的差异。
通用块层的引入为了提供一个统一的接口让文件系统实现者使用,而不用关心不同设备驱动程序的差异,这样实现出来的文件系统就能用于任何的块设备。
通用块层对不同块设备的操作转换成对逻辑数据块的操作,也就是将不同的块设备都抽象成是一个数据块数组,而文件系统就是对这些数据块进行管理。
总之,有了通用块层,不管是磁盘还是机械硬盘,对于文件系统来说都可以使用相同的接口对数据块进行读写操作。
总结抽象
到了这里,经过一层层的封装和抽象,我们整体的控制结构就出来了。
控制方式
当我们对设备进行控制后确认是否控制成功,亦或者是接收设备输出信息,都需要一种合理的控制方式。
主动轮询查询
当我们让设备控制器去读取某个数据,当读取完毕时,设备控制器会将某个寄存器的状态设置为 1,则表示读取完成。CPU 需要主动轮询查询这个寄存器的状态,来确认是否已经读取完成。这样的方式称为:主动轮询查询。
很显然,这样的方式会占用 CPU 大量的资源。
中断
于是就有了中断,中断只是硬件通过中断控制器触发,当设备任务完成,或者是输入信号,中断控制器就会通知 CPU 中断来了,CPU 会接收这个中断信号并进行处理。
听起来是不是很不错,但,有时候过多的中断也会导致系统占用大量 CPU 资源,特别是硬件中断,挡都挡不住。
DMA
针对频繁读写的磁盘,CPU 经常被中断不够友好,于是就有了 DMA(Direct Memory Access)功能,它能让设备在 CPU 不参加的情况下,将设备的数据放到内存,当然这多亏了 DMA 控制器的支持。
控制过程
经过上面对于输入输出系统的介绍,我们以键盘输入为例,它的控制过程大概是:
- 键盘按下按键
- 键盘控制器扫描得到按键数据
- 经过缓冲后统一通过总线发给 CPU 中断请求
- CPU 接收到中断请求,保存当前上下文后,调用中断处理程序进行中断处理
- 中断处理程序中的中断处理函数读取到对应字符,将对应字符放到显示设备控制器的对应的数据缓冲区
- 显示设备的设备控制器将数据显示在对应位置
- CPU 恢复中断上下文继续处理
其中肯定有很多很多细节,但我们只要知道,键盘按下后中断后处理的整个过程基本是这个意思就可以了。
总结
- 从输入输出设备的控制层层抽象,我们可以认识到,为了方便控制不同类型的事物,常常会抽象出接口来供高层来使用,让管理更加方便,这点在计算机领域很常见。
- 轮询往往没有监听来的好用,轮询往往很费性能,而这里设备的中断信号,系统的监听,往往这样的设计我们都会觉得更加合理,但其实在有些场景下还需要在对中断进行优化,中断的次数过多就会影响正常的业务运行,从而导致看起来很卡。
总的来说,对于输入输出系统中操作系统的学习其实我想知道的并不多,因为很多都与硬件设备有关,并且有着驱动程序,设备控制器帮我把关,对于操作系统本身来讲,特别是对于许多软件设计来讲,了解一些块设备的基本概念和整体的设计就够了。笨开发就只能卷到这里了。
参考链接
- linux-block-io-layer
- block layer
- DMA