设备控制器
让外设工作起来无外乎以下流程:
- 发出写命令(out指令)
- 向CPU发出中断
- 读数据到内存
但是操作系统是如何把这些输入输出设备统一管理的呢? 这就不得不说到一个“设备控制器”的组件了
- 设备控制器里有芯片,拥有自己的寄存器,用来与 CPU 进行通信
- IO控制器有相应的数据寄存器,输出时数据寄存器用于暂存CPU发来的数据,输入时,数据寄存器用于暂存设备发来的数据,之后CPU再取走数据
- CPU 通过读写设备控制器中的寄存器控制设备,如何通信?
- 分配端口,通过特殊的汇编指令操作这些寄存器,比如 in/out 类似的指令。
- 内存映射,将控制寄存器映射到内存空间,像读写内存一样操作他们的数据缓存区
为什么需要DMA?
当设备完成IO任务后触发中断到中断控制器,中断控制器就通知 CPU,对于频繁读写数据的磁盘,导致 CPU 容易经常被打断,这会干扰CPU的运行频率。
又用到了一个思想吧,在计算机中真是无处不在,就是加一个中间件。
DMA工作流程
- DMA:Direct Memory Access直接存储器存取
- DMA只在读写操作最终完成时才发出中断给CPU
文件IO
文件IO可以从多个视角进行分类
- 通过「是否利用操作系统的缓存」,可以把文件 I/O 分为直接 I/O 与非直接 I/O
- 直接 I/O,不会发生内核缓存和用户程序之间数据复制,而是直接经过文件系统访问磁盘。
- 非直接 I/O,读操作时,数据从内核缓存中拷贝给用户程序,写操作时,数据从用户程序拷贝给内核缓存,再由内核决定什么时候写入数据到磁盘。
- 阻塞IO和非阻塞IO
阻塞等待的是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程
而非阻塞省略了等待「内核数据准备好」这段时间,操作系统碰到非阻塞时可以先切出去,再通过轮询的方法进行系统调用(可以通过IO多路复用改善),如图:
- 同步IO和异步IO
我们知道I/O 是分为两个过程的:
- 数据准备的过程
- 数据从内核空间拷贝到用户进程缓冲区的过程
阻塞 I/O 会阻塞在「过程 1 」和「过程 2」,而非阻塞 I/O 和基于非阻塞 I/O 的多路复用只会阻塞在「过程 2」,所以这三个都可以认为是同步 I/O。
异步 I/O 则不同,「过程 1 」和「过程 2 」都不会阻塞。
键盘敲入字母时,期间发生了什么?
- 当用户输入了键盘字符,键盘控制器就会产生数据,并将其缓冲在键盘控制器的寄存器中,紧接着向 CPU 发送中断请求
- CPU 收到中断请求后,操作系统会保存被中断进程的 CPU 上下文,然后调用键盘的中断处理程序。
- 键盘中断处理函数的功能就是从键盘控制器的寄存器的缓冲区读取用户输入的字符,将对应的ASCII码放入读缓冲区队列,交给显示设备的驱动程序
- 显示设备的驱动程序会定时从「读缓冲区队列」读取数据放到「写缓冲区队列」,再放入到显示设备寄存器的数据缓存区,最终将数据显示在屏幕上