我们的键盘、鼠标、显示器、音响、耳机、触摸板等都是IO设备。那么操作系统是如何让显示器能显示画面。能够接收键盘的输入和鼠标输入的呢?下面我们就一步步的去看一下。
设备控制器
注:这里设备控制器到底是计算机硬件还是设备上的硬件我也没搞清楚
设备控制器是在硬件上的,再直白一点说。我们键盘有一键盘控制器,鼠标有一个鼠标控制器。每个键盘都有。每个鼠标都有。是硬件自带的一个东西。
CPU通过某些方式和设备上的设备控制器交流。显示器设备控制器可以告诉显示器展示哪些东西。音响设备控制器控制音响播放哪些声音。键盘设备控制器接收键盘输入并告诉CPU用户输入哪些字符。
设备控制器的结构
设备控制器主要由芯片+各种寄存器组成。
- 芯片:负责执行逻辑
- 寄存器:
- 命令寄存器:存储CPU下达给设备的命令
- 状态寄存器:存储CPU本次下达命令的完成状态
- 数据寄存器:CPU发送给设备或设备发送给CPU的数据存储位置
-
CPU和访问寄存器的方式
CPU是如何访问设备控制器的寄存器和数据缓冲区
端口IO:每个寄存器分配端口,CPU通过特殊的指令操作
- 内存映射IO:将内存的某些位置映射为寄存器。读内存的那块地址内容,就是读取寄存器中的内容
IO控制方式
有了设备控制器,CPU当想要与某个设备沟通时只要找相应的设备控制器即可。现在考虑一个问题,CPU要和设备控制器不断交互。那么交互方式应该是怎么样的。比如键盘输入了一段文字,键盘设备控制器如何告诉CPU,已经输入完成了呢?
自然的:
- CPU轮询:CPU一会儿问一下,一会儿再问一下
- 中断(通知):由设备控制器通知CPU,于是就产生了中断的方式(软中断、硬件中断)
- 部分设备(硬盘):DMA方式
DMA的工作方式
我们先想一下不使用DMA方式的读取文件的工作流程
- CPU发送读取XX文件的命令到磁盘设备控制器
- 磁盘设备控制器咔咔咔驱动磁盘寻道读取数据,到磁盘设备控制器的数据缓冲区中
- 磁盘设备控制器读完了,产生中断,告诉CPU可以取数据了。
- CPU忙着放下手中的线程,去告诉磁盘设备控制器(也可能是内存设备控制器),你再把数据给我加载到内存中
- (磁盘/内存)设备控制器咔咔咔将磁盘设备控制器的数据缓冲区读数据到内存中
- 最后再来个中断告诉CPU读完了
引入DMA后的流程
- CPU发送读取XX文件命令到DMA中
- DMA控制磁盘设备控制器工作,让磁盘控制器将数据先读出来,再放到内存
- 磁盘设备控制器完成工作后,告诉DMA
- DMA告诉CPU,文件已经加载到内存中了。去使用吧
设备驱动程序
我们再买鼠标和键盘时,特别一些好的键盘和鼠标时,他们都有自己的设备驱动程序的。唉,等我突然有钱了我一定把我这款50块的键盘换掉。
首先设备驱动程序就是一段功能代码,这段代码的作用是,操作设备控制器。
设备驱动程序为操作系统提供可以调用的API,操作系统调用API后,具体代码实现在设备驱动程序里。
比如读取文件,操作系统调用磁盘设备驱动程序 的读取文件API,具体怎么操作磁盘设备控制器。操作系统不关心。
既然这样,各种设备驱动程序一定会有一套统一的API,这样操作系统只要切换实现即可,无需关心具体实现。各种设备驱动程序,只需要照着操作系统的API实现即可。因此我们可以看到同一款鼠标的设备驱动程序会有Windows和Mac之分,因为每个操作系统的API接口定义可能不同呀。
中断处理
设备控制器会发送中断给CPU,CPU会根据中断类型做不同处理,那么处理逻辑代码在哪里?其实就在设备驱动程序里。
通用块层
我们设备可以分为两大类:
- 字符设备:键盘,鼠标
- 块设备:磁盘、U盘….
我们每个设备都有自己的一个设备驱动程序的话,那么设备驱动程序就太多了。那么我们对于块设备还有更高一层的抽象,就是通用块层。
文件系统只需要使用通用块的API,具体是什么块设备,磁盘也好、U盘也罢。就不再关心了。