王优秀|A 字母时,操作系统期间发生了什么...,键盘敲入( 二 )


控制器的寄存器一般会有状态标记位 , 用来标识输入或输出操作是否完成 。 于是 , 我们想到第一种轮询等待的方法 , 让CPU一直查寄存器的状态 , 直到状态标记为完成 , 很明显 , 这种方式非常的傻瓜 , 它会占用CPU的全部时间 。
那我们就想到第二种方法——中断 , 通知操作系统数据已经准备好了 。 我们一般会有一个硬件的中断控制器 , 当设备完成任务后触发中断到中断控制器 , 中断控制器就通知CPU , 一个中断产生了 , CPU需要停下当前手里的事情来处理中断 。
另外 , 中断有两种 , 一种软中断 , 例如代码调用INT指令触发 , 一种是硬件中断 , 就是硬件通过中断控制器触发的 。
但中断的方式对于频繁读写数据的磁盘 , 并不友好 , 这样CPU容易经常被打断 , 会占用CPU大量的时间 。 对于这一类设备的问题的解决方法是使用DMA(DirectMemoryAccess)功能 , 它可以使得设备在CPU不参与的情况下 , 能够自行完成把设备I/O数据放入到内存 。 那要实现DMA功能要有「DMA控制器」硬件的支持 。
王优秀|A 字母时,操作系统期间发生了什么...,键盘敲入
文章图片
DMA的工作方式如下:
CPU需对DMA控制器下发指令 , 告诉它想读取多少数据 , 读完的数据放在内存的某个地方就可以了;
接下来 , DMA控制器会向磁盘控制器发出指令 , 通知它从磁盘读数据到其内部的缓冲区中 , 接着磁盘控制器将缓冲区的数据传输到内存;
当磁盘控制器把数据传输到内存的操作完成后 , 磁盘控制器在总线上发出一个确认成功的信号到DMA控制器;
DMA控制器收到信号后 , DMA控制器发中断通知CPU指令完成 , CPU就可以直接用内存里面现成的数据了;
可以看到 , CPU当要读取磁盘数据的时候 , 只需给DMA控制器发送指令 , 然后返回去做其他事情 , 当磁盘数据拷贝到内存后 , DMA控制机器通过中断的方式 , 告诉CPU数据已经准备好了 , 可以从内存读数据了 。 仅仅在传送开始和结束时需要CPU干预 。
设备驱动程序
虽然设备控制器屏蔽了设备的众多细节 , 但每种设备的控制器的寄存器、缓冲区等使用模式都是不同的 , 所以为了屏蔽「设备控制器」的差异 , 引入了设备驱动程序 。
王优秀|A 字母时,操作系统期间发生了什么...,键盘敲入
文章图片
设备控制器不属于操作系统范畴 , 它是属于硬件 , 而设备驱动程序属于操作系统的一部分 , 操作系统的内核代码可以像本地调用代码一样使用设备驱动程序的接口 , 而设备驱动程序是面向设备控制器的代码 , 它发出操控设备控制器的指令后 , 才可以操作设备控制器 。
不同的设备控制器虽然功能不同 , 但是设备驱动程序会提供统一的接口给操作系统 , 这样不同的设备驱动程序 , 就可以以相同的方式接入操作系统 。 如下图:
王优秀|A 字母时,操作系统期间发生了什么...,键盘敲入
文章图片
前面提到了不少关于中断的事情 , 设备完成了事情 , 则会发送中断来通知操作系统 。 那操作系统就需要有一个地方来处理这个中断 , 这个地方也就是在设备驱动程序里 , 它会及时响应控制器发来的中断请求 , 并根据这个中断的类型调用响应的中断处理程序进行处理 。
通常 , 设备驱动程序初始化的时候 , 要先注册一个该设备的中断处理函数 。
王优秀|A 字母时,操作系统期间发生了什么...,键盘敲入
文章图片
我们来看看 , 中断处理程序的处理流程:
在I/O时 , 设备控制器如果已经准备好数据 , 则会通过中断控制器向CPU发送中断请求;
保护被中断进程的CPU上下文;
转入相应的设备中断处理函数;
进行中断处理;